Synchronized原理
Synchronized的底层理解
1,monitor是一个计数器
2,为什么会有Synchronized关键字:
当程序出现并发的时候,访问修改一个共享变量的时候就会出现线程安全问题,Synchronized的出现就是为了解决线程安全问题
3,锁机制的两种特性:
互斥性:同一个时间点只允许某一个线程持有某个对象锁,如果其他线程需要获取到同样的对象锁就必须等到前一个线程释放。
可见性:在锁被释放之前,对共享数据做出的改变必须让其他线程感知到,及时获取最新数据,防止脏数据。
Synchronized(this||object对象)
在Java中每一个对象都有一个moniter对象,这个对象其实就是Java对象的锁,通常我们称为内置锁或对象锁,一个类有多个对象,所以每个对象都有独立的锁互不干扰。
Synchronized(object.class)
在Java中,针对每一个类都有一个锁,我们称为类锁,实际上类锁也是通过对象锁实现的,即类的class对象,每一个类只有一个class对象,所以只有一个类锁。
Java里面每一个对象都有已个monitor对象,monitor我们也可以理解为监视器
某一个线程占有这个对象的时候monitor就会进行+1,其他线程发现monitor不为0的时候就会进行等待,直到上一个线程释放这个对象monitor进行-1为0的时候,才进行执行
同一个线程可以对同一个对象进行多次加锁,重入锁,当这个线程第二次对同一个对象加锁的时候monitor还是会+1
Synchronized的原理分析
线程堆栈的分析互斥性:
当thread-0线程先获取到同一个锁的时候,他的状态是TIME_WATTING,其他线程则BLOCKD,阻止其他线程进行访问
thread-1没有获取到锁那么他的状态为BLOCKD,等待对象释放
所以他就有了互斥性,当thread-1去获取锁的时候,发现有线程已经获取了,他的总阻止数为1.
JVM指令分析:
Sycchronized同步代码块
当Synchronized同步代码块的时候我们发现,他是使用moniter计数器来进行标记
monitorenter代表互斥的开始 moniter进行+1操作
monitorexit代表互斥的结束moniter进行-1操作(正常退出)
这里有两个monitorexit 前者为正常出口,后者为异常出口
Sycchronized同步方法
当Synchronized同步方法的时候,我们发现他并没有monitorenter与monitorexit两个关键字,那他是怎么进行标识的呢?
Synchronized同步方法的时候,他又一个特殊的ACC_SYNCHRONIZED标记,来标识这个互斥的开始。LineNumberTable代表互斥的结束。
以上就是Synchronized在使用的时候,他的底层又一些什么动作。
使用Synchronized注意的问题:
1 与moniter关联的对象不能为空
2 Synchronized的作用域比较大要谨慎使用,一个类集成了thread,重写了run方法那么再给run方法进行加锁就会导致作用域过大
3 不同的moniter企图锁不同的对象
4 多个锁交叉出现死锁
实列对象与monitor的关系
对象头中主要存放数据为:加锁的数据,他又分为下列三个区域
当一个Java对象被某一个线程占用的时候,则该java对象的Mark Word字段中LockWord指向monitor的起始地址
实列变量主要存放的是一些数据,比如int =1 int =2
填充数据暂时不管
Java虚拟机对Synchronized优化
Mark Word里面存放的锁状态
在JDK1.6之前就只有重量锁
在JDK1.6之后就新加入了,偏向锁,轻量级锁,重量级锁
偏向锁:
某个对象第一次被某个线程占有的时候,他会把是否为偏向锁置为1,记录线程id,当下一次这个线程再来的时候他就不需要经过CAS算法了,这样竞争到锁的几率会大一点。
https://www.cnblogs.com/bjlhx/p/10555194.html