有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java为什么ArrayBlockingQueue构造函数在JDK 8中需要锁

There is no practical need for a constructor to be synchronized, because it would lock the object under construction, which is normally not made available to other threads until all constructors for the object have completed their work.

上面是https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.8.3

但我在ArrayBlockingQueue的构造函数中找到了锁。为什么使用它

public ArrayBlockingQueue(int capacity, boolean fair,  Collection<? extends E> c) {
        this(capacity, fair);
        final ReentrantLock lock = this.lock;
        lock.lock(); // Lock only for visibility, not mutual exclusion
        try {
            int i = 0;
            try {
                for (E e : c) {
                    checkNotNull(e);
                    items[i++] = e;
                }
            } catch (ArrayIndexOutOfBoundsException ex) {
                throw new IllegalArgumentException();
            }
            count = i;
            putIndex = (i == capacity) ? 0 : i;
        } finally {
            lock.unlock();
        }
    }

共 (1) 个答案

  1. # 1 楼答案

    注释// Lock only for visibility, not mutual exclusion告诉了你这件事。根据CPU的不同,我们可能会遇到这样的情况:构造线程“离开”我们的构造函数,但字段尚未初始化(因此,在我们的示例中,线程离开ArrayBlockingQueue构造函数,但我们的countputIndexitems字段尚未初始化,其他一些线程开始使用offer/add方法)。在LinkedBlockingQueue中使用相同的锁定策略。此外,JVM还可以在方法/构造函数中对字节码指令进行重新排序。最后,可能存在这样一种情况:一个线程可以在另一个线程完成构建对象之前获得引用

    在这里,你可以阅读更多关于它的信息:

    Constructor synchronization in Java

    此外,还有很多关于内存可见性的博客帖子