7

考虑下面的 Java 示例。请注意,没有一个类成员变量被声明为volatile. 如果我正确理解了内存模型和“发生在之前”规则,Java 实现可以优化该run()方法,使其永远运行,即使另一个线程调用该stopNow()方法。发生这种情况是因为该run()方法中没有强制线程stop多次读取值的内容。那是对的吗?如果不是,为什么不呢?

class Example implements Runnable {
    boolean stop = false;
    int value = 0;

    public void stopNow() {
       stop = true;
    }

    public int getValue() {
        return value;
    }

    @Override
    public void run() {
        // Loop until stop is set to true.
        while (!stop) {
            ++value;
        }
        return;
    }
}
4

2 回答 2

4

可以由另一个线程修改,但这不是保证。这也不是线程安全的。要保证从另一个线程查看变量,您需要执行以下任何操作

只有在以下情况下,才能保证一个线程对字段所做的更改对其他线程可见:

  • 写入线程释放同步锁,读取线程随后获取相同的同步锁。
  • 如果一个字段被声明为易失性,则写入它的任何值都会在写入
    线程执行任何进一步的内存操作之前被写入线程刷新并使其可见(即,出于
    手头的目的,它会立即刷新)。Reader 线程必须
    在每次访问时重新加载 volatile 字段的值。
  • 线程第一次访问对象的字段时,它会看到该字段的初始值或自其他线程写入以来的值。
  • 当线程终止时,所有写入的变量都被刷新到主内存。例如,如果一个线程在另一个线程终止时使用 Thread.join 进行同步,则可以保证看到该
    线程产生的效果(参见第 4.3.2 节)。

有用的 SO 线程

于 2014-02-05T04:28:49.653 回答
2

这是正确的。这就是您可能想要使用volatile.

于 2014-02-05T04:26:40.950 回答