一 . 概述
可见性问题:
什么是可见性问题?可见性问题的原因是什么?
可见性问题完全是JVM的结构造成的,JVM为了高速的运行,对每一个线程进行了线程栈的设计,在线程栈之中设置了高速的缓存.
缓存之中存在共享变量的副本,在有些时候,因为来不及维护副本和实体的一致性可能造成问题,这种问题就是可见性问题.
注意: 当我们解决的原子性的同时也就完成了可见性的问题的解决.
二 . 可见性性问题的例子:
public class VisiableProblem extends Thread { private boolean isRunning = true; public boolean isRunning() { return isRunning; } public void setRunning(boolean isRunning) { this.isRunning = isRunning; } public void run() { System.out.println("进入了run..............."); while (isRunning) { } System.out.println("isUpdated的值被修改为为false,线程将被停止了"); } public static void main(String[] args) throws InterruptedException { VisiableProblem volatileThread = new VisiableProblem(); volatileThread.start(); Thread.sleep(1000); volatileThread.setRunning(false); // 停止线程 } }
我们希望主线程可以同步标记位停止子线程,但是很让人失望,子线程无法终止.
原因就是子线程使用了副本的内容,这个副本永远是true的.
三 . 使用volatile解决可见性
我们只要在
private volatile boolean isRunning = true;
增加一个volatile就能解决这个问题.
volatile的关键词的作用:
[1]保证副本和主存之间的一致性
[2]打破指令重排序(这个在后面会说一下)
当我们看到了volatile的作用之后就知道怎么为什么能解决上述的问题了.
四 .分析
volatile可以解决可见性问题,但是无法解决原子性.
而线程的安全性问题的解决需要的是原子性而不是可见性,也就是说可见性是原子性的一个保证,但无法保证原子性.
这也就决定了我们不能依靠volatile来实现同步.