Java Volatile和ArrayBlockingQueue以及其他并发对象

Java Volatile和ArrayBlockingQueue以及其他并发对象,java,multithreading,volatile,java.util.concurrent,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&g

我理解(或者至少我认为我理解;)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;
    ...
}
如果数组中的元素不是易失性的(我知道声明数组本身对元素本身没有任何影响),如何保证插入到
items[putIndex]
中的值从另一个线程可见? 另一个线程不能保存数组的缓存副本吗


谢谢

注意,
排队
私有的
。查找对它的所有调用(
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();
    }
}

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

据我的理解,volatile是不需要的,因为所有BlockingQueue实现都已经有了与
ConcurrentHashMap
不同的锁定机制。
如果您查看队列的公共方法,您将发现一个保护并发访问的
ReentrantLock

是的,我注意到了,但我不知道锁是记忆屏障。我以为是同步的,但不确定锁。你确定吗?因为lock()唯一要做的就是将当前线程标记为独占所有者并设置内部状态。我看不出它与内存barrierok有什么关系。你是对的,在java文档中,它说锁必须提供与synchronized相同的内存语义。所以我想知道它内部是如何工作的。可能是编译器对这些锁进行了特定的处理?
public void put(E e) throws InterruptedException {
    checkNotNull(e);
    final ReentrantLock lock = this.lock;
    lock.lockInterruptibly();
    try {
        // Do stuff.
        enqueue(e);
    } finally {
        lock.unlock();
    }
}