Java 为什么Volatile不';当一个字段的值取决于它以前的值时,它不起作用

Java 为什么Volatile不';当一个字段的值取决于它以前的值时,它不起作用,java,volatile,Java,Volatile,我偶然发现了这句话,我想不出理由 当字段的值取决于其属性时,Volatile不起作用 先前值 任何带有示例的解释都是非常值得赞赏的。“不起作用”是一个非常模糊的说法,但我怀疑问题的关键是,如果您有两个线程各自使用此代码执行一个循环: field = field + 1 。。。那么,即使是不稳定的,每次迭代都是有效的: 阅读 使用我们读取的值执行计算 写 如果一个线程执行读取,然后另一个线程执行写入,那么当第一个线程执行写入时,它实际上将忽略第二个线程的写入 回到我们的例子,如果你有两个线程,每

我偶然发现了这句话,我想不出理由

当字段的值取决于其属性时,Volatile不起作用 先前值

任何带有示例的解释都是非常值得赞赏的。

“不起作用”是一个非常模糊的说法,但我怀疑问题的关键是,如果您有两个线程各自使用此代码执行一个循环:

field = field + 1
。。。那么,即使是不稳定的,每次迭代都是有效的:

  • 阅读
  • 使用我们读取的值执行计算
  • 如果一个线程执行读取,然后另一个线程执行写入,那么当第一个线程执行写入时,它实际上将忽略第二个线程的写入

    回到我们的例子,如果你有两个线程,每个线程执行了一百万次
    field=field+1
    ,那么
    field
    的值的总增加量可能不会达到两百万。

    “不起作用”是一个相当模糊的说法,但我怀疑问题的关键在于,如果有两个线程分别使用以下代码执行循环:

    field = field + 1
    
    。。。那么,即使是不稳定的,每次迭代都是有效的:

  • 阅读
  • 使用我们读取的值执行计算
  • 如果一个线程执行读取,然后另一个线程执行写入,那么当第一个线程执行写入时,它实际上将忽略第二个线程的写入

    回到我们的示例,如果有两个线程分别执行
    field=field+1
    的一百万次迭代,那么
    field
    值的总增加量可能不会达到两百万次。

    以下是一个示例:

    volatile int i:
    
    public void m() {
      if (i == 0) i = 1;
      else i = 2;
    }
    
    您可以让两个线程检查该条件,查看i是否为0并将其设置为1,尽管您可能希望两次运行该方法会将i设置为2。这是一个经典的“先检查后行动”场景

    问题在于,波动性为您提供了可见性保证,但没有原子性保证。

    以下是一个示例:

    volatile int i:
    
    public void m() {
      if (i == 0) i = 1;
      else i = 2;
    }
    
    您可以让两个线程检查该条件,查看i是否为0并将其设置为1,尽管您可能希望两次运行该方法会将i设置为2。这是一个经典的“先检查后行动”场景


    问题是,波动性为您提供了可见性保证,但没有原子性保证。

    FYI…我在Bruce EckelFYI的《Java思考》一书中找到了这条语句…我在Bruce EckelFYI的《Java思考》一书中找到了这条语句感谢您通过检查然后行动场景解释这一点。我对波动性为何/如何依赖于变量的先前值感到困惑。“当一个字段的值取决于其先前的值时,波动性行为不一定会得到保证”是一个更合适的说法吗?感谢您通过先检查后行动的场景来解释这一点。我对波动性为何/如何依赖于变量的先前值感到困惑。“当一个字段的值取决于其先前的值时,波动性行为不一定会得到保证”是一个更合适的说法吗?在您的解释之后,这个说法似乎是模糊的。谢谢你提供的细节。经过你的解释,这个声明看起来确实很模糊。谢谢你提供的细节。