Multithreading 何时不使用挥发油?

Multithreading 何时不使用挥发油?,multithreading,concurrency,volatile,java-memory-model,non-volatile,Multithreading,Concurrency,Volatile,Java Memory Model,Non Volatile,是否曾经有过这样一种情况:我们不会将volatile用于线程之间共享的对象的类成员?我的理解是volatile关键字确保对象值不是由线程缓存的,而是总是从内存中读取的,但不将其标记为volatile并不意味着它总是被线程缓存。所以我的问题是,我们能不能通过不将此类类标记为volatile来保证任何事情,或者代码是否会对随机行为开放 编辑:我明白,对任何事情使用volatile都不能保证我的逻辑的正确性。我的问题更多的是理论性的,是我试图理解Java内存模型。如果不将变量声明为volatile,并

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


编辑:我明白,对任何事情使用volatile都不能保证我的逻辑的正确性。我的问题更多的是理论性的,是我试图理解Java内存模型。

如果不将变量声明为volatile,并且在访问它之前不执行任何类型的互斥锁,那么是的,您总是会面临不可预测的行为和竞争条件/死锁

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

首先,不应该用缓存来解释并发性。因为版本2的java内存模型更正式,需求也更弱。所以,这一切都是在命令之前发生的

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

因此,您可以使用语义之前发生的任何操作,而不是volatile。发件人:

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

  • 对线程的start()调用发生在 启动线程

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

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


嗯,
final
也常用于共享对象的成员……final是否意味着该成员将被视为线程本地成员?如果我也不添加final呢?将所有
都设置为volatile
提供了与使每个方法
同步一样多的线程安全性。您仍然会遇到错误的行为,例如,如果您需要看到一个类的两个成员处于一致状态,那么同步getter和volatile都不能保证这一点。您需要整个状态的原子副本或外部同步或<代码>易失性
在我看来很少有用,因为保证是非常具体的。仅仅像过时一样抛出
易失性
对线程安全没有任何作用,而
易失性
字段限制了优化器并需要额外的工作(内存围栏IIRC)。因此,如果您没有使用volatile的具体原因,为什么要使用它呢?我知道,对所有事情使用volatile都不能保证我的逻辑的正确性。我的问题更多的是理论性的,是我试图理解Java内存模型。这里我关心的不是太多的竞争条件和死锁。我是从看到最新更新的线程的角度来提问的。这是一样的。不能保证任何其他线程都能看到更新的最新程度,除非您强制执行在并发性中调用的关系之前发生。这是有道理的!非常感谢。你认为还有其他的情况吗?谢谢你的解释,丹尼斯。请参阅更新的(添加了澄清)问题。好的,简短回答“我们可以通过不将此类类标记为volatile来保证任何事情,或者代码会对随机行为开放吗?”-是的,我们可以。看看我的列表,例如,您可以使用synchronized在锁下写入和读取共享变量。在这种情况下,volatile是多余的。太好了!这正是我想要的。谢谢