synchronized (原子性 有序性 可见性) volatile (原子性 可见性)
1.volatile本质是在告诉jvm当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取;synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住。
2.volatile仅能使用在变量级别;synchronized则可以使用在变量、方法、和类级别的。
3.volatile仅能实现变量的修改可见性,并不能保证原子性;而synchronized则可以保证变量的修改可见性和原子性。
4.volatile不会造成线程的阻塞;synchronized可能会造成线程的阻塞。
5.volatile标记的变量不会被编译器优化;synchronized标记的变量可以被编译器优化。
原子性:所谓原子操作是指不会被线程调度机制打断的操作;这种操作一旦开始,就一直运行到结束
例如:int i = 1; 该语句为原子操作,因为执行这句话后i的值一定是等于1.
反例:int i= 0; i++ ; 其中 i++不是原子操作,在多线程中会有线程安全问题,i++其实分为三个步骤,1. 读取变量i的值;2:对i进行加一的操作;3.将计算后的值再赋值给变量i
synchronized :能保证原子操作。1、锁住主内存,2、执行工作内 3、将工作内存写入主内存。4.释放锁
但synchronized块不同于真正意义的原子性操作,执行时是可以中断的
原因:单例模式
volatile 防止指令重排序 从而保证原子操作
class Singleton {
private (volatile) static Singleton instance = null;
public static Singleton instance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null)
instance = new Singleton();//step1
}
}
return instance;
}
}
有序性:
可见性:当一个线程修改了共享变量后,其他线程能够立即得知这个修改
当线程获取锁时会从主内存中获取共享变量的最新值,释放锁的时候会将共享变量同步到主内存中。从而,synchronized具有可见性。同样的在volatile分析中,会通过在指令中添加lock指令,以实现内存可见性。因此, volatile具有可见性
参考:https://www.jianshu.com/p/cf57726e77f2
、https://blog.csdn.net/weixin_45110404/article/details/90453221
https://blog.csdn.net/niexianglin_csdn/article/details/47361003