如下所示,该程序有一个共享变量,flag但不带volatile:public class T { public static void main(String[] args) { TT jump = new TT(() -> { while (true) { if (TT.flag) { System.out.println("jump"); break; } } }); jump.start(); new TT(() -> { TT.flag = true; // P1 LocalDateTime t1 = LocalDateTime.now(); while (true) { if (Duration.between(t1, LocalDateTime.now()).toMillis() > 100) { break; } } System.out.println("flag"); }).start(); } static class TT extends Thread { public static boolean flag = false; public TT(Runnable o) { super(o); } }}程序总是正常返回。所以我相信设置为 的行已P1在其他线程中更新。flagtrueflag但为什么?flag不是易失性的,为什么它的值会立即更新?总是!
1 回答
泛舟湖上清波郎朗
TA贡献1818条经验 获得超3个赞
但为什么?flag不是易失性的,为什么它的值会立即更新?总是!
你只是幸运而已;或不幸,取决于你的观点。我在 Ideone 上尝试了这个,发现它超时而不是正常终止。
请记住:无法观察到并发错误并不等同于不存在并发错误。
您对代码最有把握的是,根据规范,您可以证明不存在错误。这并不意味着代码就能正常工作;而是意味着代码可以正常工作。这只是意味着问题出在 JVM 实现上。
特别是,您无法证明此代码将正常工作,因为第二个线程中的写入与第一个线程中的读取之间不存在发生之前关系。flag
添加volatile
创建了这种保证,因为易失性写入发生在易失性读取之前。
这并不是说没有 volatile 就永远无法工作,只是不能保证:JVM 只需要至少按照规范要求的频率刷新线程的缓存值,但可以更频繁地执行此操作,或者实际上根本不缓存值。
添加回答
举报
0/150
提交
取消