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

Java 为什么ArrayBlockingQueue构造函数在JDK 8中需要锁,java,synchronization,Java,Synchronization,实际上不需要同步构造函数,因为它会锁定正在构造的对象,在对象的所有构造函数完成工作之前,其他线程通常无法使用该对象 上面是 但我在ArrayBlockingQueue的构造函数中找到了使用的锁。为什么使用它 public ArrayBlockingQueue(int capacity, boolean fair, Collection<? extends E> c) { this(capacity, fair); final ReentrantLoc

实际上不需要同步构造函数,因为它会锁定正在构造的对象,在对象的所有构造函数完成工作之前,其他线程通常无法使用该对象

上面是

但我在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();
        }
    }

public ArrayBlockingQueue(int-capacity,boolean-fair,Collection注释
//锁定仅用于可见性,而非互斥
告诉您这一点。根据CPU的不同,我们可能会遇到这样的情况:构造线程“离开”构造函数,但字段尚未初始化(因此,在我们的示例中,线程离开了
ArrayBlockingQueue
构造函数,但我们的
计数
putIndex
字段尚未初始化,其他一些线程开始使用
提供
/
添加
方法)。在
LinkedBlockingQueue
中使用了相同的锁定策略。此外,JVM还可以在方法/构造函数中对字节码指令进行重新排序。最后,可能会出现一种情况,即一个线程可以在另一个线程完成构建对象之前获得引用

在这里,您可以阅读更多信息:


此外,还有许多关于内存可见性的博客文章。

注释
//锁定仅用于可见性,而不是互斥
告诉您。根据CPU的不同,我们可能会遇到这样的情况:构造线程“离开”构造函数,但字段尚未初始化(因此,在我们的示例中,线程离开了
ArrayBlockingQueue
构造函数,但我们的
计数
putIndex
字段尚未初始化,其他一些线程开始使用
提供
/
添加
方法)。在
LinkedBlockingQueue
中使用了相同的锁定策略。此外,JVM还可以在方法/构造函数中对字节码指令进行重新排序。最后,可能会出现一种情况,即一个线程可以在另一个线程完成构建对象之前获得引用

在这里,您可以阅读更多信息:

此外,还有许多关于内存可见性的博客文章