码迷,mamicode.com
首页 > 其他好文 > 详细

Synchronized实现原理

时间:2020-04-16 14:57:58      阅读:59      评论:0      收藏:0      [点我收藏+]

标签:null   reference   stat   说明   添加   代码块   final   inf   解锁   

Synchronized的四种锁状态:无锁状态,偏向锁,轻量级锁,重量级锁

 

轻量级级锁的实现原理

轻量级锁的使用场景:如果一个对象虽然有多线程访问,但多线程访问的时间是错开的,也就是说没有竞争,那么完全可以用轻量级锁来优化

假设有两个方法同步块,利用同一个对象加锁

static final Object obj = new Object();
public static void method1(){
    synchronized(obj){
        //同步块A
        method2();
    }
}

public static void method2(){
    synchronized(obj){
        //同步块B
    }
}
  • 创建锁记录(Lock Record)对象,每个线程的栈帧都会包含一个锁记录的结构,内部可以存储锁定对象的MarkWord

技术图片

 

 

  • 让锁记录中Object reference指向锁对象,并尝试用cas替换Object的MarkWord, 将MarkWord 的值存入锁记录

技术图片

 

  •  如果cas替换成功,对象头中存储了锁记录地址和状态00,表示由该线程给对象加锁,这时图示如下

技术图片

 

 

 

  •  如果cas替换失败,则有以下两种情况
  1. 如果是其它线程已经持有了该Object的轻量级锁,这时候表明有竞争,进入锁膨胀过程
  2. 如果是自己执行了synchronized锁重入,那么再添加一条Lock Record作为重入的计数

技术图片

  • 当退出synchronized代码块(解锁)的时候,如果有取值为null的锁记录,表示有重入,这时重置锁记录,表示重入计数减一

技术图片

 

  • 当推出synchronized代码块(解锁)时,锁记录的值不为null,那么将使用cas将Mark Word的值恢复给对象头
  1. 成功,则解锁成功
  2. 失败,说明轻量级锁进行了锁膨胀或已经升级为重量级锁,进入重量级锁解锁流程

 

重量级锁的实现原理

给一个对象(obj)加锁,会在操作系统层面获取一个监视器Monitor,有时候也叫管程)对象,对象obj的Markword会指向该Monitor对象,原本Markword中存放的分代年龄等信息会存放在Monitor对象里。Monitor里的Owner指向持有该对象obj的锁的线程Thread_1。当其它线程Thread_2, Thread_3试图获取对象obj的锁时,发现Owner已经指向了Thread_1,也就是Thread_1已经获取该对象的锁时后,那么Monitor的EntryList就会将Thread_2,Thread_3放到EntryList里面,等到Thread_1释放锁后,再从EntryList里取出一个线程,将Monitor里的Owner指向该进程。每个对象都有自己的Monitor

技术图片

 

 图中Thread_1释放锁,Thread_2获得obj的锁,

技术图片

 

 

需要注意的是:只有在用synchronized关键字修饰后,才会有上述对象markword指向Monitor,否则的话,是不会去向操作系统申请这一Monitor对象的。而且,必须是重量级锁才会申请这个Monitor

Synchronized实现原理

标签:null   reference   stat   说明   添加   代码块   final   inf   解锁   

原文地址:https://www.cnblogs.com/Chsy/p/12712625.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!