锁里面的AtomicInteger有什么用

what is the use of AtomicInteger inside lock

在 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

那里有两把锁:

private final ReentrantLock putLock = new ReentrantLock();

private final ReentrantLock takeLock = new ReentrantLock();

put 方法确实受到 putLock 的保护,但是访问 count 的任何其他线程仍然可以更新它(除非它是另一个 put)。为确保它已正确更新,它必须是 Atomic

LinkedBlockingQueue 使用两个不同的锁,putLocktakeLock 允许并发的 puttake 操作在不阻塞彼此的情况下进行,假设队列中已经有节点但容量没有用完(或根本没有限制)。

所以在这种情况下,count 可能会被两个线程同时访问。由于消费者和生产者线程使用不同的锁,锁本身并没有在生产者和消费者之间建立必要的内存可见性保证,实际上是 count 的原子更新。

除此之外,还有非阻塞操作,如size()remainingCapacity() 无需持有锁即可访问count。此外,一些操作,如 peek()poll()(没有超时)有一个捷径,在获取锁之前测试 count 是否为零,到 return null 计数为零时立即不锁定。