gpt4 book ai didi

java - 使用 ` LinkedBlockingQueue`可能会导致空指针异常

转载 作者:行者123 更新时间:2023-12-01 16:43:17 24 4
gpt4 key购买 nike

最近在学习java并发编程。我知道 final 关键字可以保证安全发布。然而,当我阅读LinkedBlockingQueue源码时,我发现headlast字段没有使用final 关键字。我发现在put方法中调用了enqueue方法,并且enqueue方法直接将值赋值给last.next。此时,last 可能为 null,因为 last 未使用 final 声明。我的理解正确吗?虽然lock可以保证last读写线程安全,但是lock能否保证last是一个正确的初始值而不是 null

public class LinkedBlockingQueue<E> extends AbstractQueue<E>
implements BlockingQueue<E>, java.io.Serializable {
transient Node<E> head;
private transient Node<E> last;
public LinkedBlockingQueue(int capacity) {
if (capacity <= 0) throw new IllegalArgumentException();
this.capacity = capacity;
last = head = new Node<E>(null);
}
private void enqueue(Node<E> node) {
// assert putLock.isHeldByCurrentThread();
// assert last.next == null;
last = last.next = node;
}

public void put(E e) throws InterruptedException {
if (e == null) throw new NullPointerException();
// Note: convention in all put/take/etc is to preset local var
// holding count negative to indicate failure unless set.
int c = -1;
Node<E> node = new Node<E>(e);
final ReentrantLock putLock = this.putLock;
final AtomicInteger count = this.count;
putLock.lockInterruptibly();
try {
/*
* Note that count is used in wait guard even though it is
* not protected by lock. This works because count can
* only decrease at this point (all other puts are shut
* out by lock), and we (or some other waiting put) are
* signalled if it ever changes from capacity. Similarly
* for all other uses of count in other wait guards.
*/
while (count.get() == capacity) {
notFull.await();
}
enqueue(node);
c = count.getAndIncrement();
if (c + 1 < capacity)
notFull.signal();
} finally {
putLock.unlock();
}
if (c == 0)
signalNotEmpty();
}
}

最佳答案

根据这篇博文https://shipilev.net/blog/2014/safe-public-construction/甚至写信给一个final构造函数中的属性足以实现安全初始化(因此您的对象将始终安全发布)。和capacity属性声明为 final .

In short, we emit a trailing barrier in three cases:

A final field was written. Notice we do not care about what field was actually written, we unconditionally emit the barrier before exiting the (initializer) method. That means if you have at least one final field write, the final fields semantics extend to every other field written in constructor.

关于java - 使用 ` LinkedBlockingQueue`可能会导致空指针异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61821328/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com