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 楼答案
注释
// Lock only for visibility, not mutual exclusion
告诉了你这件事。根据CPU的不同,我们可能会遇到这样的情况:构造线程“离开”我们的构造函数,但字段尚未初始化(因此,在我们的示例中,线程离开ArrayBlockingQueue
构造函数,但我们的count
,putIndex
,items
字段尚未初始化,其他一些线程开始使用offer
/add
方法)。在LinkedBlockingQueue
中使用相同的锁定策略。此外,JVM还可以在方法/构造函数中对字节码指令进行重新排序。最后,可能存在这样一种情况:一个线程可以在另一个线程完成构建对象之前获得引用在这里,你可以阅读更多关于它的信息:
Constructor synchronization in Java
此外,还有很多关于内存可见性的博客帖子