In this section from java.util.concurrent.LinkedBlockingQueue.put() method, I think there is no need of AtomicInteger. Considering there is only one thread inside lock(). Am I correct?
putLock.lockInterruptibly();
try {
while (count.get() == capacity) {
notFull.await();
}
enqueue(node);
c = count.getAndIncrement();
if (c + 1 < capacity)
notFull.signal();
} finally {
putLock.unlock();
}
I checked many questions, but can not find answer. My question: there is only one thread inside lock, so why to use AtomicInteger here
The LinkedBlockingQueue
uses two different locks, putLock
and takeLock
to allow concurrent put
and take
operation to proceed without blocking each other, assuming that there are already nodes in the queue but the capacity has not exhausted (or not limited at all).
So it this case, count
may be accessed by two threads concurrently. Since the consumer and producer threads use different locks, the locks themselves do not establish the necessary memory visibility guarantees between the producer and consumer, it is in fact the atomic update of the count
which does.
Besides that, there are also non-blocking operations, like size()
or remainingCapacity()
which access count
without holding a lock. Also, some operations, like peek()
and poll()
(without timeout) have a short-cut, testing count
for zero before acquiring the lock, to return null
immediately without locking when the count is zero.