- volatile
保证可见性
,在工作内存中,每次使用volatile变量都必须先从主内存刷新最新值,使用后立刻同步回主内存(volatile变量依然有工作内存的拷贝,但由于它特殊的操作顺序(每次使用前都需要刷新),所以看起来如同直接在主内存中读写访问一般)(将use和load动作相关联,即use前必须是load,load后必须是use;将assign和store相关联,即store前必须是assign,assign后必须是store)
Java内存模型中八种基本操作; - volatile
保证有序性
(禁止指令重排序优化,jkd1.5以后重新修复):先行先发生原则中volatile变量规则:对一个volatile变量的写操作先行发生于(能被后面的读操作感知到)后面(时间上)对这个变量的读操作。
通过内存屏障(Memory Barrier)实现,指令重排序时不能把后面的指令重排序到内存屏障之前的位置。 - volatile
不能保证原子性
。如果我们对一个volatile修饰的变量进行多线程下的自增操作,还是会出现线程安全问题。根本原因在于volatile关键字无法对自增进行安全性修饰,因为自增分为三步,读取、+1、写入。中间多个线程同时执行+1操作,还是会出现线程安全性问题。
volatile与synchronized
- volatile轻量级,只能修饰变量。synchronized重量级,还可修饰方法;
- volatile只能保证数据的可见性,不能用来同步,因为多个线程并发访问volatile修饰的变量不会阻塞。(常用于循环判断标志);
- synchronized不仅保证可见性,而且还保证原子性,因为,只有获得了锁的线程才能进入临界区(操作共享变量的代码段),从而保证临界区中的所有语句都全部执行。多个线程争抢synchronized锁对象时,会出现阻塞。
总结
volatile可见性(use和load、assign和store),有序性(禁止重排序,happens-before,内存屏障)
原子性:synchronized
可见性:volatile、synchronized、final
有序性:volatile、synchronized(相当于保证只有一个线程执行代码段,保证有序性)
volatile典型用法
volatile Boolean asleep;
While(!asleep)
countSomeSheep();
网友评论