原子性,有序性,可见性

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;
}
}

有序性:

在java内存模型中说过,为了性能优化,编译器和处理器会进行指令重排序;也就是说java程序天然的有序性可以总结为:如果在本线程内观察,所有的操作都是有序的;如果在一个线程观察另一个线程,所有的操作都是无序的。在单例模式的实现上有一种双重检验锁定的方式

可见性:当一个线程修改了共享变量后,其他线程能够立即得知这个修改

当线程获取锁时会从主内存中获取共享变量的最新值,释放锁的时候会将共享变量同步到主内存中。从而,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

原文地址:https://www.cnblogs.com/tpcwlilacfover/p/12163876.html