原子性
定义:原子性是指在一个操作中cpu不可以在中途暂停然后再调度,即不被中断操作,要不全部执行完成,要不都不执行。就好比转账,从账户A向账户B转1000元,那么必然包括2个操作:从账户A减去1000元,往账户B加上1000元。2个操作必须全部完成。
关键字:synchronized
1 | private long count = 0; |
在上述代码中,将执行以下步骤:
- 将count从主存读取到工作内存中的副本
- +1运算
- 将结果写入工作内存
- 将工作内存中的值刷回主存(什么时候刷入由操作系统决定,不确定的)
可见性
定义:当一个线程修改了共享变量的值,其他线程会马上知道这个修改。当其他线程要读取这个变量的时候,最终会去内存中读取,而不是从缓存中读取。
关键字:volatile、synchronized、final
有序性
定义:虚拟机在进行代码编译时,对于那些改变顺序之后不会对最终结果造成影响的代码,虚拟机不一定会按照我们写的代码的顺序来执行,有可能将他们重排序。实际上,对于有些代码进行重排序之后,虽然对变量的值没有造成影响,但有可能会出现线程安全问题。
1 | int a = 0; |
1 | 如果按照1234执行,结果为: |
关键字:volatile、synchronized
volatile本身就包含了禁止指令重排序的语义,而synchronized关键字是由“一个变量在同一时刻只允许一条线程对其进行lock操作”这条规则明确的。
小结
- synchronized关键字同时满足以上三种特性,但是volatile关键字不满足原子性。
- 在某些情况下,volatile的同步机制的性能确实要优于锁(使用synchronized关键字或java.util.concurrent包里面的锁),因为volatile的总开销要比锁低。
- 我们判断使用volatile还是加锁的唯一依据就是volatile的语义能否满足使用的场景(原子性)