参考书:《Java并发编程艺术》
在学习这一块知识之前,可以先学习一下JMM相关的知识,回过来再看这个问题,就很好理解:https://www.cnblogs.com/perferect/p/13680158.html
可见性:对一个volatile变量的读,总能看到任意线程对这个volatile变量最后的写入。
原子性:对于一个volatile修饰的变量的读/写具有原子性,但是类似于volatile++ 这种复合操作不具有原子性
注意:很多博客都写volatile变量不具有原子性,这是他们对上面原子性这段话产生了错误的理解
举个例子
volatile int a = 0;
上面也就是说:
如果只是 a =10; 这种写入操作时没有问题的;
但是 a = a + a * 10 + 1 ; 这种同时进行读和写的操作时无法保证对volatile变量操作的原子性的;
至于什么原因?
其实指是通过#LOCK指令锁定内存中的缓存并写回到内存区,并使用缓存一致性机制来保证修改的原子性。此操作被称为“缓存锁定”,缓存一致性机制会阻止同时修改有两个以上处理器缓存的内存区间。
JMM编译器重排序
生成指令执行过程中
对于普通同步方法,锁是当前实例对象。
对于静态同步方法,锁是当前类的Class对象
对于同步方法快,锁是Synchonized括号里配置的对象
JMM编译器重排不同:
volatile:是通过在volatile变量的独写操作前后增加屏障实现防止重排序的
synchronized: 是通过增加临界区,防止临界区内变量逸出。
执行指令的不同:
volatile:通过#LOCK前缀,刷新数据到主内存中
synchronized:是通过monitor,对指令块进行监听,通过monitorenter和monitorexit进行匹配
线程基础知识03-volatile和synchronized
原文:https://www.cnblogs.com/perferect/p/13679249.html