2

是否有过我们不会对线程之间共享的对象的类成员使用 volatile 的情况?我的理解是 volatile 关键字确保对象值不被线程缓存,而是始终从内存中读取,但不将其标记为 volatile 并不意味着它将始终被线程缓存。所以我的问题是,我们是否可以通过不将此类标记为 volatile 来保证任何事情,或者代码是否会对随机行为开放?

编辑:我知道对所有事情都使用 volatile 并不能保证我的逻辑的正确性。我的问题更多是理论上的,是我理解 Java 内存模型的尝试。

4

3 回答 3

4

首先,您不应该用缓存来解释并发性。由于版本 2 java 内存模型更正式并且要求更弱。所以,这一切都是关于先发生的顺序。

如果您需要对某些变量进行并发访问,则必须通过发生前对写入和读取进行排序。这是最重要的事情。Volatile 只是这种排序的一种实现方式。

因此,您可以使用任何具有happens-before语义的操作来代替volatile。来自JLS

  • 监视器上的解锁发生在该监视器上的每个后续锁定之前。

  • 线程上的 start() 调用发生在已启动线程中的任何操作之前。

  • 线程中的所有操作都发生在任何其他线程
    从该线程上的 join() 成功返回之前。

  • 任何对象的默认初始化发生在程序的任何其他
    操作(默认写入除外)之前。

于 2014-11-20T22:20:58.770 回答
3

至少不可变对象永远不需要任何类型的同步。因此,对不可变类的字段使用volatile是没有意义的。

于 2014-11-19T22:11:16.453 回答
0

如果您不将变量声明为易失性,并且在访问它之前不进行任何类型的互斥锁,那么是的,您总是将自己暴露于不可预测的行为和竞争条件/死锁。

于 2014-11-19T22:10:06.033 回答