定义:如果线程A中的一个操作对线程B是可见的,那么这个操作的执行成功后结果将立刻被线程B发现。
image.png
多核时代,每颗 CPU 都有自己的缓存,当多个线程在不同的 CPU 上执行时,这些线程操作的是不同的 CPU 缓存。线程 A 操作的是 CPU-1 上的缓存,而线程 B 操作的是 CPU-2 上的缓存,很明显,这个时候线程 A 对变量 V 的操作对于线程 B 而言就不具备可见性了。
在多线程的环境下,如果某个线程首次读取共享变量,则首先到主内存中获取该变量,然后存入工作内存中,以后只需要在工作内存中读取该变量即可。同样如果对该变量执行了修改的操作,则先将新值写入工作内存中,然后再刷新至主内存中。但是什么时候最新的值会被刷新至主内存中是不太确定,一般来说会很快,但具体时间不知。
要解决共享对象可见性这个问题,我们可以使用volatile关键字或者是加锁


可见性可以解决,但是很难被证明出来!网上的例子都是错的。

一个常见的可见性的例子

实际上这个例子不是可见性的问题,因为在while里面加入一句输出hello,(System.out.println()里面有synchornized),线程会停止运行。
参见 hllvm-group.iteye.com/group/topic/34932

  1. public class Test {
  2. // volatile
  3. static boolean flag = true;
  4. public static void main(String[] args) throws InterruptedException {
  5. new Thread(()->{
  6. while(flag){
  7. }
  8. }).start();
  9. TimeUnit.SECONDS.sleep(1);
  10. new Thread(()->{
  11. flag=false;
  12. }).start();
  13. }
  14. }

而是编译优化指令重排引起的问题,
image.png