【问题标题】:Java volatile keyword - why this code terminates [duplicate]Java volatile关键字-为什么此代码终止[重复]
【发布时间】:2020-02-28 13:45:58
【问题描述】:

我正在使用 Java 中的 volatile 关键字,并且我有这段代码试图显示一个线程不会看到另一个线程引入的更改,除非我们将数据声明为 volatile。我期待下面的代码永远不会终止,因为我没有将共享数据声明为易失性。知道为什么这段代码实际上会终止吗?

public class VolatileTest {

    public static void main(String[] args) throws InterruptedException {
        var holder = new Holder();
        new Thread(() -> {
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) { }
            for(int i = 0; i<100000; i++) {
                holder.counter++;
            }
        }).start();
        var t = new Thread(() -> {
            while(holder.counter < 10000) {
                System.out.println("Jestem w pętli");
                try {
                    Thread.sleep(400);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t.start();
        t.join();
    }

    static class Holder {
        int counter = 0;
    }

}

【问题讨论】:

  • 你在哪里使用volatile关键字?顺便说一句:永远不要写 catch (InterruptedException e) { } 异常应该被处理,至少记录
  • 允许线程缓存非易失变量的值。这并不能保证他们不会看到变化。
  • 这个答案解释了为什么你的代码在没有 volatile 关键字 stackoverflow.com/a/30956634/5862990 的情况下“有效”
  • 这就是为什么测试多线程程序的正确性是一个难题。 Java 语言规范保证如果您遵守某些规则,您的程序将以某种方式运行。但是,它确实保证如果您违反规则,您的程序将出现异常行为。最坏的情况是你测试了一些软件,它通过了你的所有测试,你把它寄给了一个重要的客户,然后在六个月后当他们升级他们的操作系统时,**** 击中了粉丝。它发生了。不要问我是怎么知道的!

标签: java multithreading volatile


【解决方案1】:

如果您不使用volatileThread 1 可能不会立即看到Thread 2 的变化,但最终会在将来发生一次,当Thread 2 清空 CPU 缓存到主内存时会发生这种情况。在您的示例中,如果您在counter 字段上使用volatile,则在您调用holder.counter++ 时写入线程将始终写入主内存,而每次调用holder.counter &lt; 10000 时,读取线程将从主内存中读取。

【讨论】:

    猜你喜欢
    • 2015-06-03
    • 2011-04-05
    • 2011-05-25
    • 2016-02-12
    • 1970-01-01
    • 2019-01-19
    • 2018-12-21
    • 2011-03-30
    相关资源
    最近更新 更多