特点
- 使用MESI协议(使得数据被修改了,状态可被修改可以立即看到),保证了线程间的可见性,但无法保证原子性
- 禁止指令重排(指令重排是指多个指令的并发执行,提高了效率),但会影响可见性,使用内存屏障实现,在多线程下,禁止指令重排可以避免后续的线程获得未初始化的变量
无法保证原子一致性
static volatile int num=0;
public static void main(String[] args) throws InterruptedException, ExecutionException {
for(int i=0;i<1000;i++){
new Thread(()->{
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
num = num+1 ;
System.out.println(num);
}).start();
System.out.println(num);
}
}
如下图所示,volatile无法保证原子一致性
volatile存在的意义
volatile最大的意义是禁止cpu指令重排,避免后面的线程访问前面线程的还未初始化的变量,如以下代码
class NumStoreDemo{
private NumStoreDemo() {
}
private static volatile NumStoreDemo numStore;
private static volatile int num = 0;
private static volatile int nums = 0;
public void add() throws InterruptedException {
synchronized (this){
num=num+1;
/*System.out.println(num);*/ } }
public static NumStoreDemo instance() throws InterruptedException {
if(numStore==null){
synchronized (NumStoreDemo.class){
if(numStore==null){
numStore=new NumStoreDemo();
nums=nums+1;
System.out.println("初始化 "+numStore+","+nums);
}
} }
return numStore;
}
}