synchronized锁能否保证两段代码始终输出'END'?
问题1解答
没法保证程序一定输出'END'。
按Java内存模型(JMM)的规则来解释:
- 主线程在
synchronized(Visibility.class)块里把i改成1,解锁之后,这个写操作的结果只对之后拿到同一锁的操作有顺序保证。 - 线程1里
if (i == 1)的检查是在空synchronized块外面做的,读i的动作没被synchronized的内存屏障覆盖。JVM可能会优化这段代码——比如把i的值缓存到线程1自己的工作内存里,因为线程1本身没改i,JVM可能觉得i不会变,结果就是线程1永远看不到主线程写的i=1。
你本地跑总能出'END'是因为具体JVM实现或者硬件缓存的巧合,但JMM没给绝对保证。
问题2解答
这个情况能保证程序一定输出'END'。
改完之后,线程1的synchronized块里加了int x = i;,触发了关键的内存逻辑:
- 每次进
synchronized块,线程1会先加锁,JMM会强制让线程1工作内存里的共享变量(包括i)失效,读i的时候必须从主内存拿最新值。 - 主线程改完
i=1解锁后,按JMM的顺序规则,主线程的解锁操作早于线程1之后的加锁操作,所以线程1在synchronized块里读到的i肯定是主线程写的1。 - 线程1读到
i=1后,这个值会同步到自己的工作内存,下一次循环检查if (i == 1)时,直接读工作内存里的新值,就能触发输出'END'并退出循环。
内容的提问来源于stack exchange,提问作者Anonemous
相关产品推荐
相关产品推荐

