在main函数里执行Thread.sleep(2000); 之后更新了未用volatile修饰的变量flag,然而线程并没有停下来。将Thread.sleep(2000); 注释掉后线程就会停下来。我个人的理解是线程唤醒后并没有更新flag到工作内存。但是直接更新flag,线程停了下来,说明把更新后的flag读到了工作内存。这是为何?
在main函数里执行Thread.sleep(2000); 之后更新了未用volatile修饰的变量flag,然而线程并没有停下来。将Thread.sleep(2000); 注释掉后线程就会停下来。我个人的理解是线程唤醒后并没有更新flag到工作内存。但是直接更新flag,线程停了下来,说明把更新后的flag读到了工作内存。这是为何?
当取消sleep后,你的Thread2线程可能还没运行起来呢,就被主线程将flag改为false了,读到Thread2工作内存中的flag就是false,所以直接就停了,此时的i应该是0,因为根本没读到过值为true的flag。
使用sleep是确保Thread2线程已经运行起来,之后再修改flag为false。因为没有可见性保证,所以Thread2工作内存中的flag一直是true,无法停下来。
15 回答8.4k 阅读
8 回答6.2k 阅读
1 回答4k 阅读✓ 已解决
3 回答2.2k 阅读✓ 已解决
2 回答3.1k 阅读
2 回答3.8k 阅读
3 回答1.7k 阅读✓ 已解决
volatile 保证一定会刷新,但是不volatile也不一定其他线程看不见;
我在我本地测试, 用您的代码, sleep(0)和sleep(1)是可以刷的;sleep(2)或者2ms以上就不行了;
因为main线程和t子线程是并行执行的, 有可能:
子线程run之前,main线程sleep时, 后面的flag赋值完成, 也做了刷新; 但是这不是一定的;
我们记得volatile是肯定刷的就行了, 非volatile的可能刷, 也可能不刷, 确定性不能保证.