可见性之volatile关键字
什么是可见性
cpu在执行代码的时候,为了减少变量访问的时间消耗可能会将代码中访问的变量值缓存到该CPU的缓存区,所以在相应代码再次访问某个变量时,读到的值可能来自于缓存区而不是主存,同样,代码对这些缓存过的变量值的修改也可能只是被写入到缓存区,而没有回写到主存,且每个CPU都有自己的缓存区,因此一个CPU缓存区中的内容对于其他CPU是不可见的
可见性就是一个线程对于共享变量的修改能够及时的被其他线程看到
共享变量是指如果一个变量在多个线程的工作内存中都存在副本,那么这个变量就是这几个线程的共享变量
在java规范中指出:为了获得更快的速度,允许线程保存共享变量的私有拷贝,而且只有在线程进入或者离开同步代码块时才会将私有拷贝与共享内存中的原始值进行比较
可见性的实现方式
- synchronized(保证原子性和可见性) synchronized关键字
- volatile(只保证可见性),如果变量已在synchronized代码块中,或者为常量时,没有必要使用volatile修饰,比synchronized更快,不会引起线程上下文的切换和调度
先举一个例子,来看一下不使用volatile的时候
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| public class TestVolatile { public static void main(String[] args) { ThreadDemo runnable = new ThreadDemo(); new Thread(runnable).start();
while (true){ if(runnable.isFlag()){ System.out.println("----------"); break; } } } }
class ThreadDemo implements Runnable{
private boolean flag; @Override public void run() { try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } flag = true;
System.out.println(Thread.currentThread().getName()+"---flag:"+flag); }
public boolean isFlag() { return flag; }
public void setFlag(boolean flag) { this.flag = flag; } }
|