Volatile和synchronized的实现原理
前言
对于Volatile和synchronized,学过多线程的人再熟悉不过了,Volatile主要实现的是内存可见性,synchronized主要是获得锁。具体原理以及过程更多的是在JVM里去实现的,jdk只是简单地封装,在以后的文章里,我会分享一下JVM的Hotspot锁相关源码。
什么是JMM
JMM(Java Memory Mode)Java内存模型。JMM主要定义了线程和主内存之间的抽象关系。JMM主要是在并发过程中如何处理可见性,原子性,有序性的问题
JMM的共享与非共享
首先我们思考一下,什么对象是内存共享的?什么不是?
线程之间共享:
java中,堆内存里:实例域,静态域,数组元素等
堆内存的特性:线程之间共享
线程之间不共享:
局部变量,方法参数、异常等
并发编程中的重点问题
1、线程之间如何通信?wait(),notify(),notifyall()
命令编程模型里:
线程A/B什么时候从主内存获取数据刷新本地缓存?
答:不确定
正是因为不确定,才导致了线程安全与可见性的问题
怎么解决?
使用Volatile和synchronized
a) 共享内存 -隐式通信
b) 消息传递 -显式通信
2、线程之间如何同步?
在共享内存的并发模型中,同步是显示做的:synchronized
在消息传递的并发模型中,由于消息的发送必须在消息接收之前,所以同步是隐式
Volatile保证可见性原理
功能:原子性,可见性;但不能做到复合操作的原子性
//复合操作不能保证原子性举例:
//多线程操作add方法
Volatile int i;
public void add(){
i++;
}
1.对于声明了Volatile的变量进行写操作的时候,JVM会向处理器发送一条Lock前缀的指令。会把这个变量所在缓存行的数据写回到系统内存
2.在多处理的情况下,保证各个处理器缓存一致性的特性,就会实现缓存一致性协议
synchronized锁的原理
功能:可重入锁,互斥性,可见性
synchronized的实现代码在Hotspot里,jdk只是简单封装,为了验证流程,我们写一个测试类:
public class App2 {
public static void main(String[] args) throws InterruptedException{
synchronized (App2.class){}
test();
}
public static synchronized void test(){}
}
然后编译,看字节码文件.class文件
然后对字节码文件执行
javap -v App2.class
得到:
基于JVM实现的monitorenter ,monitorexit
实现了获得锁,运行,释放锁的过程