内部锁定中AtomicInteger的用途是什么

Gau*_*wal 4 concurrency multithreading atomic java-8

在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();
    }
Run Code Online (Sandbox Code Playgroud)

我查了很多问题,但找不到答案.我的问题:锁内只有一个线程,所以为什么要在这里使用AtomicInteger

Hol*_*ger 7

LinkedBlockingQueue使用两个不同的锁,putLocktakeLock允许并行puttake操作而不会阻塞彼此进行,假设有在队列中已经节点但容量尚未用尽(或根本不局限于).

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

除此之外,还有非阻塞操作,如没有持有锁的访问size()remainingCapacity()访问count.此外,某些操作,如peek()poll()(没有超时)有一个快捷方式,count在获取锁之前测试为零,null当计数为零时立即返回而不锁定.

  • `使用不同的锁,锁本身没有建立必要的内存可见性保证` - 优秀!通常,锁会建立内存可见性,但它们必须是所有线程使用的*相同*锁 (3认同)

Eug*_*ene 5

那里有两个锁:

private final ReentrantLock putLock = new ReentrantLock();

private final ReentrantLock takeLock = new ReentrantLock();
Run Code Online (Sandbox Code Playgroud)

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