java - 一个线程中对非 volatile 成员变量的赋值是否保证在另一个线程中可见?

标签 java multithreading java-memory-model

考虑下面的 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;
    }
}

最佳答案

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

Changes to fields made by one thread are guaranteed to be visible to other threads only under the following conditions:

  • A writing thread releases a synchronization lock and a reading thread subsequently acquires that same synchronization lock.
  • If a field is declared as volatile, any value written to it is flushed and made visible by the writer thread before the writer
    thread performs any further memory operation (i.e., for the purposes
    at hand it is flushed immediately). Reader threads must reload the
    values of volatile fields upon each access.
  • The first time a thread accesses a field of an object, it sees either the initial value of the field or a value since written by some other thread.
  • As a thread terminates, all written variables are flushed to main memory. For example, if one thread synchronizes on the termination of another thread using Thread.join, then it is guaranteed to see the
    effects made by that thread (see §4.3.2).

有帮助 SO thread

关于java - 一个线程中对非 volatile 成员变量的赋值是否保证在另一个线程中可见?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21568516/

相关文章:

java - 将 json 的特定值传递给另一个 Activity

java - 如何根据build.xml中定义的taskdef操作列表中的要求执行taskdef操作?

java - 如何只比较 java.sql.TimeStamp 的时间

.net - 在 .Net 应用程序中管理来自单个 Socket 的并发读取

java - 我在 Swift 和 Java 中的代码。 Swift 给出错误,但 Java 没有。有什么不同吗?

wpf - 如何在单独的线程上创建和显示 WPF 窗口?

.net - WCF线程-无响应的UI

java - 如何使用 volatile 变量编写简单的线程安全类?

java - 同步数据读/写到/从主存储器

Java 堆空间监控——我们做错了吗?