在java.util.concurrent.LinkedBlockingQueue.put()方法的本节中,我认为不需要AtomicInteger。考虑到lock()中只有一个线程。我是对的吗?
putLock.lockInterruptibly();
try {
while (count.get() == capacity) {
notFull.await();
}
enqueue(node);
c = count.getAndIncrement();
if (c + 1 < capacity)
notFull.signal();
} finally {
putLock.unlock();
}
我查了很多问题,但找不到答案。我的问题:锁内只有一个线程,所以为什么要在这里使用AtomicInteger
答案 0 :(得分:7)
LinkedBlockingQueue
使用两个不同的锁putLock
和takeLock
,允许并发put
和take
操作继续进行而不会相互阻塞,假设存在已经是队列中的节点,但容量尚未耗尽(或根本不受限制)。
所以在这种情况下,count
可以由两个线程同时访问。由于使用者和生产者线程使用不同的锁,因此锁本身不会在生产者和使用者之间建立必要的内存可见性保证,实际上它是count
的原子更新。
除此之外,还有非阻止操作,例如size()
或remainingCapacity()
,无需持有锁即可访问count
。此外,某些操作(如peek()
和poll()
(没有超时)都有一个快捷方式,在获取锁之前测试count
为零,在没有锁定的情况下立即返回null
当计数为零时。
答案 1 :(得分:5)
那里有两把锁:
private final ReentrantLock putLock = new ReentrantLock();
private final ReentrantLock takeLock = new ReentrantLock();
put
方法确实受putLock
保护,但访问count
的任何其他线程仍然可以更新它(除非它是另一个put
)。为确保正确更新,必须为Atomic
。