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

标签 java synchronization

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的构造函数中使用了LOCK。为什么使用它?

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

最佳答案

注释 //Lock only forvisibility, notmutualclusion 告诉您这一点。根据 CPU 的不同,我们可能会遇到这样的情况:构造线程“离开”我们的构造函数,但字段尚未初始化(因此在我们的示例中,线程离开 ArrayBlockingQueue 构造函数,但我们的 countputIndexitems 字段尚未初始化,并且其他一些线程使用 offer/add 方法启动)。 LinkedBlockingQueue 中使用了相同的锁定策略。此外,JVM 有能力在我们的方法/构造函数中重新排序字节码指令。最后,可能存在这样的情况:一个线程可以在另一个线程完成构造对象之前获取引用。

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

Constructor synchronization in Java

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

关于java - 为什么 ArrayBlockingQueue 构造函数在 JDK 8 中需要 Lock,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51781217/

相关文章:

java - 如何设计一个包含已知和未知键值对映射的 Java 类?

java - 在 JAVA 对象中存储和获取值

java - 如何添加列表中单词的每个字符的位置

javascript - Gulp 文件与 browsersync 的集成

c# - .NET 的离线同步选项

java - 在 Java 中等待条件

java - 为什么 Fortify 将其标记为未发布的资源?

java - Objective C 相当于 java 中的 intern()

java - 布局似乎有问题,JButton 在调整窗口大小时显示意外行为

java - 使用 libgdx 在运行时使用文本生成纹理