java - Volatile 和 ArrayBlockingQueue 以及其他可能的并发对象

标签 java multithreading volatile java.util.concurrent

我理解(或者至少我认为我理解;))volatile 关键字背后的原理。 查看 ConcurrentHashMap 源代码时,您可以看到所有节点和值都声明为 volatile,这是有道理的,因为可以从多个线程写入/读取值:

static class Node<K,V> implements Map.Entry<K,V> {
    final int hash;
    final K key;
    volatile V val;
    volatile Node<K,V> next;
    ...
}

但是,查看 ArrayBlockingQueue 源代码,它是一个正在从多个线程更新/读取的普通数组:

private void enqueue(E x) {
    // assert lock.getHoldCount() == 1;
    // assert items[putIndex] == null;
    final Object[] items = this.items;
    items[putIndex] = x;
    if (++putIndex == items.length)
        putIndex = 0;
    count++;
    notEmpty.signal();
}

如果数组中的元素不是易变的(我知道声明数组本身没有对元素本身有任何影响)? 另一个线程不能保存数组的缓存副本吗?

谢谢

最佳答案

请注意 enqueueprivate。查找对它的所有调用(offer(E)、offer(E, long, TimeUnit)、put(E))。请注意,每一个看起来像:

public void put(E e) throws InterruptedException {
    checkNotNull(e);
    final ReentrantLock lock = this.lock;
    lock.lockInterruptibly();
    try {
        // Do stuff.
        enqueue(e);
    } finally {
        lock.unlock();
    }
}

因此您可以得出结论,enqueue 的每次调用都受到 lock.lock() ... lock.unlock() 的保护所以你不需要 volatile 因为 lock.lock/unlock 也是一个内存屏障。

关于java - Volatile 和 ArrayBlockingQueue 以及其他可能的并发对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43069910/

相关文章:

java - 根据多列的比较在数据库中创建列

java - 在 Java 中从 URL 解析 XML 时出现 MalformedByteSequenceException

java - Jhipster:应用程序正在运行,但浏览器上没有输出

java - 参数类型中的名称是否确定该类是否是通用的?

c++ - 如何锁定由属于 2 个不同类的 2 个线程修改的数据结构

Java - 不实例化对象时是否需要 static 和 volatile?

java - Java中ExecutorService关闭时显示友好消息?

c++ - 为什么 std::lock() 在使用我自己的 unique_lock 对象时会导致无限循环?

c# - 重新排序围绕 volatile 的操作

java - 如果我省略 Java 的 volatile 关键字会发生什么?