什么是可见性?
一个线程修改了共享变量的值,其他线程也能看到最新修改的值 。
下图是一段存在线程可见性问题的代码:
在主线程中修改两个变量的值,不一定对副线程可见,副线程有可能读取到为false的ready和为111的num。
为什么会出现这样的结果?
线程的交叉执行,重排序加线程交叉执行,共享变量更新后的值没有在工作内存和主内存中及时更新。
首先要对java内存模型有一个大概的概念,每个线程有自己的工作内存,除此之外还有主内存区域,对变量的读写不一定会及时写入到主存,想要对其它线程可见,需要将工作内存中的写入同步到主存,并且同步到各个线程的工作内存中。
线程对共享变量的读写都必须在自己的工作内存中进行,而不能直接在主内存中读写。不同线程不能直接访问其他线程的工作内存中的变量,线程间变量值的传递需要主内存作为桥梁。
如何实现可见性?
在被synchronized保护的代码块中对共享变量进行写入,或者使用volatile修饰变量。
需要注意:Volatile通过内存屏障和禁止重排序来实现线程可见性。但不能保证原子性。