volatile的知识回顾:
- 写入:写入变量的时候,直接写到主内存,并且失效其他线程的本地内存;
- 读取:读取的时候,直接读取的主内存或者未失效的本地内存;
以上描述不精确,但主要思路是OK的,思路与缓存设计异曲同工
本篇不做知识科普,不再详述,我们来看看volatile应用场景:
- 一写多读场景
这种场景不需要考虑两个线程同时写变量导致变量不正确,但是需要考虑实时性;
这种情况一般是做信号使用,如果不用volatile标识变量,那么线程A写、更新了变量后,其余的B/C/D/E....线程,不保证合适能够读到最新的值,但是加了volatile后,能保证读到的一定是最新值,保证了信号传递的效率;
2.乐观锁场景
我们来看一个典型的乐观锁(伪代码,不能运行,这种操作一般都是调用Unsafe类来操作,原子性操作请使用java.util.concurrent.atomic,不用自己写乐观锁)
public class VolatileTest {
private volatile int a = 0;
public static void main(String[] args){
int expect ;
do{
expect = a;
}while (!compareAndSet(expect, expect+1));
}
}
可想而知,如果没有volatile
来标识a变量,那么expect = a;
这行读到最新的值要花费更多的时间,而乐观锁是一直空转了,就会多N次空转,白白浪费了大好的CPU资源
volatile
在乐观锁场景意义重大
网友评论