volatile是什么
volatile是类型修饰符
volatile是java虚拟机提供的轻量级同步机制
volatile特性
1.可见性
2.不保证原子性
3.禁止指令重排
volatile的作用是作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值
JMM(java内存模型)
说到volatile不得不提到JMM(Java Memory Model),JMM保证了程序之间的可见性。
由于JVM运行程序的实体是线程,而每个线程创建时JVM都会为其创建一个工作内存(有些地方称之为栈空间),工作内存是每个线程的私有数据区域,而Java内存模型中规定所有变量都储存在主内存,主内存
是共享内存区域,所有线程都可以访问,但线程对变量的操作(读取、赋值等)必须在工作内存中进行。
所有首先要将变量从主内存拷贝到自己的工作内存空间,然后对变量进行操作,操作完成后再将变量写回主内存。不能直接操作主内存中的变量,各个线程中的工作内存中存储着主内存中的变量副本拷贝,因此不同的线程间无法访问对方的工作内存,线程间的通信(传值)必须通过主内存来完成。这个通信过程即保证了可见性。
原子性是什么意思
不可分割,完整性,也即某个线程正在做某个具体业务时,中间不可以被加塞或者被分割。需要整体完整要么同时成功,要么同时失败。
如何保证原子性
1.使用sync关键字
2.使用JUC包下的AtomicInteger等
指令重排现象
多线程环境中线程交替执行,由于编译器优化重排的存在,两个线程中使用的变量能否保证一致性是无法确定的,结果无法预测。
禁止指令重排小总结
volatile实现禁止指令重排优化,从而避免多线程环境下程序出现乱序执行的现象。
内存屏障(Memory Barrier)
又称内存栅栏,是一个CPU指令,它的作用有两个:
1.保证特定操作的执行顺序
2.保证某些变量的内存可见性(实现volatile的内存可见性)
通过插入内存屏障禁止在内存屏障前后的指令执行重排序优化。内存屏障另外一个作用是强制刷出各种CPU的缓存数据,因此CPU上的线程都能读取到这些数据的最新版本。
如何使线程安全性获得保证?
工作内存与主内存同步延迟现象导致的可见性问题:
可以使用synchronized或volatile关键字解决,它们都可以使一个线程修改后的变量立即对其他线程可见。