Java内存模型要求lock,unlock,read,load,assign,use,store,write这8个操作都具有原子性,但对于64位的数据类型(long或double),在模型中定义了 一条相对宽松的规定,允许虚拟机将没有被volatile修饰的64位数据的读写操作划分为两次32位的操作来进行,即允许虚拟机实现选择可以不保证64位数据类型的load,store,read,write这4个操作的原子性,即long和double的非原子性协定。
ps:一般情况下不需要把用到的long和double变量专门声明为volatile
原子性:
- 由Java内存模型来直接保证的原子性变量操作包括read,load,assign,use,store,write,我们可以大致认为基本数据类型的访问读写是具备原子性的
- 在synchronized块之间的操作也具有原子性
可见性:
可见性是指当一个线程修改了共享变量的值,其他线程能够立即得知这个修改
可见性的实现:Java内存模型是通过变量修改后将新值同步回主内存,在变量读取前从主内存刷新变量值,将主内存作为传递媒介
volatile的特殊规则保证了新值能立即同步回主内存,以及每次使用前立即从主内存中刷新
还有能够实现可见性的关键字:synchronized和final
- 同步代码块的可见性是由“对一个变量执行unlock操作之前,必须先把此变量同步回主内存中”
- final的可见性是指:被final修饰的字段在构造器中一旦初始化完成,并且构造器没有吧“this”的引用传递出去,那在其他线程中就能看见final的值
有序性:
如果在本线程内观察,所有操作都是有序的,如果在一个线程中观察另一个线程,所有操作都是无序的:首先“线程内表现为串行语义”;其次“指令重排序”和“工作内存和主内存同步延迟”
Java语言提供了volatile和synchronized两个关键字来保证线程之间操作的有序性
synchronized关键字具备以上三种特性