volatile可以保证数据在线程间的可见性,例如我们可以用boolean来控制循环,多个线程之间的数据共享。volatile最底层是lock add汇编指令完成的
作用:
1.线程间数据可见性
2.禁止指令重排序
写一个小例子说明线程可见性:
这里线程可能会一直执行,即使下面线程修改了boo为false,但是线程之间不一定可见(为什么这么说呢?首先堆内存值boo,每个线程对其操作都会copy一份到自己的工作内存中,如果主内存值被修改,其他线程如果空闲可能会去读取一遍,但是也可能不去读取,即使读取了,也有延时。)
加上volatile关键字可以在修改主内存值时,同步到所有线程。
volatile还有一个功能是禁止指令重排序,例如一个对象,其中很多属性,创建对象大致分为以下几部分:申请空间==》默认值==》初始化==》将初始化的值赋值给栈内存的对象指针。
重排序是在超高并发下,创建对象的几个步骤可能会有乱序执行的风险,这样就会导致对象中个别属性并没有完全初始化完成,此时拿到的对象不为null,但是数据又不正确。
例:单例创建对象,高并发下满足第一道判断的有很多线程,如线程A,阻塞的同时其他线程B创建好了对象,如果未加volatile,可能创建的对象不是我们想要的,锁释放后,线程B进入同步块,此时对象满足第二道判断不为null,线程B直接拿走对象使用,引发了数据安全性。
还有很重要的一点:volatile只能保证线程之间数据可见性,不能保证原子性,例:
加锁
所以:volatile绝对不能替代锁