Java多线程系列之可见性

2018-04-25  本文已影响0人  MakeItSimple

何为可见性?

线程A修改了共享变量Var1,线程B能看到这个修改吗?这就是所谓的可见性。
在多线程的世界里,每个线程都有自己的工作内存,里面存储着各种变量。线程方法中的局部变量不会有同步的问题。但是,不同线程之间的共享变量就不一定了。最典型的共享变量就是某个类的静态成员。对于这些共享变量,每个线程都会把共享变量拷贝一份副本,因为JVM只允许线程修改自己工作内存中的变量值。换言之,不同线程变量之间的传递必须经过主内存。如下图:


JMM示意图

这样一来,线程1如果修改了共享变量,线程2不一定能够看到。除非线程1在更新自己的副本之后,还能把线程副本中的新值写入到主内存中。同时,线程2能重新从主内存中刷新这个共享变量。

另外,还有一个现象就是指令重排序。它是编译器或处理器为了提高程序性能而做的优化。有如下几种:

这个重排序会导致代码书写的顺序与实际执行顺序不同的现象。
重排序不会给单线程带来内存可见性的问题。但是,多线程中程序交错执行时,重排序可能会造成内存可见性问题。下图是《Java并发编程实践》中的一个例子,能说明可见性的问题。


重排序的栗子

综上,多线程情况下,某个线程中变量值的修改可能在其他线程中看不到,这样的问题就是多线程下的可见性问题。
以下方法可以解决可见性问题。

1、synchronized加锁

JMM关于synchronized的两条规定:

2、volatile

volatile关键字使用注意事项

synchronized和volatile之间的区别

其他

参考文章

https://www.cnblogs.com/rocomp/p/4780532.html
Java并发编程实践

上一篇下一篇

猜你喜欢

热点阅读