volatile 会传播到实例成员吗?
Does volatile propagate to instance members?
假设有一些像这样声明和实例化的简单容器
class Test {
private volatile List<Object> list = new ArrayList<>();
}
,对其读写有锁保护; synchronized
未使用关键字。尽管 Test.list
被声明为 volatile,但其成员字段中的 none 如 ArrayList.elementData
也带有此修饰符。现在,在多线程应用程序中,它会表现得像 volatile 容器吗?换句话说,某个线程提交给 ArrayList.elementData
的更改是否会立即被所有其他线程可见?
一般答案是否定的:volatile
仅在对引用变量的读取和写入之间建立先行关系。如果两个线程同时访问变量中引用的对象的内部字段,还是需要同步机制
在您的情况下,最好的方法似乎是使用同步列表,或 java.util.concurrent
包中的一些包装器。
简答:没有。因此,数组元素始终是非易失性的(即使数组本身被声明为易失性)。您需要使用 List
的特殊并发友好实现。通常 java.util.concurrent.CopyOnWriteArrayList
符合需要。如果你只分配一次 list
变量,那么 volatile 关键字不会改变任何东西(在这种情况下最好使用 final
)。
假设有一些像这样声明和实例化的简单容器
class Test {
private volatile List<Object> list = new ArrayList<>();
}
,对其读写有锁保护; synchronized
未使用关键字。尽管 Test.list
被声明为 volatile,但其成员字段中的 none 如 ArrayList.elementData
也带有此修饰符。现在,在多线程应用程序中,它会表现得像 volatile 容器吗?换句话说,某个线程提交给 ArrayList.elementData
的更改是否会立即被所有其他线程可见?
一般答案是否定的:volatile
仅在对引用变量的读取和写入之间建立先行关系。如果两个线程同时访问变量中引用的对象的内部字段,还是需要同步机制
在您的情况下,最好的方法似乎是使用同步列表,或 java.util.concurrent
包中的一些包装器。
简答:没有。因此,数组元素始终是非易失性的(即使数组本身被声明为易失性)。您需要使用 List
的特殊并发友好实现。通常 java.util.concurrent.CopyOnWriteArrayList
符合需要。如果你只分配一次 list
变量,那么 volatile 关键字不会改变任何东西(在这种情况下最好使用 final
)。