读这篇牛掰的精简文章你需要掌握的前提知识是java内存模型,和并发编程三大特性
valatile
语义上指确保一个变量的更新对其他线程是马上可见,禁止对指令进行重排序;当一个变量被声明为valatile
,线程对变量的写操作会直接刷回主存,不会保存至工作内存(本地内存cache);线程对变量的读操作,不会去工作内存中读取,而是直接从主存中读取,这就保证了变量的修改对其他线程都是可见;禁止重排序是指对变量进行volatile声明后,对该变量有前后依赖关系的指令禁止重新排序;
直接对共享变量操作会造成线程安全问题;
/**
* @Author lsc
* @Description <p>线程不安全 </p>
* @Date 2019/11/17 13:17
*/
public class Unsafe {
private int zxzxz;
public int getZxzxz() {
return zxzxz;
}
public void setZxzxz(int zxzxz) {
this.zxzxz = zxzxz;
}
}
syncronized是一种内部锁机制;内部锁是一种排它机制,即一个线程获取到锁,其他线程必须等该线程放弃锁的拥有权才能获取到锁;通常我们称内部锁是监视器(monitor),其能保证共享变量的原子性操作,和线程对变量更新操作的可见性;但缺点也很明显,使用syncronized会带来上下文线程切换的额外开销;
/**
* @Author lsc
* @Description <p>syncronized线程安全示例 </p>
* @Date 2019/11/17 13:20
*/
public class SafaForSyn {
private int zxzxz;
public int getZxzxz() {
return zxzxz;
}
public synchronized void setZxzxz(int zxzxz) {
this.zxzxz = zxzxz;
}
}
/**
* @Author lsc
* @Description <p>volatile线程安全 </p>
* @Date 2019/11/17 13:29
*/
public class SafeForVolatile {
private volatile int zxzxz;
public int getZxzxz() {
return zxzxz;
}
public void setZxzxz(int zxzxz) {
this.zxzxz = zxzxz;
}
}
volatile 并不能保证变量的原子性操作,所以其是一种弱同步;syncronized能保证变量的原子性,可见性和指令的有序性,其是一种强同步;