Synchronized实现原理
Posted chsy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Synchronized实现原理相关的知识,希望对你有一定的参考价值。
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替换失败,则有以下两种情况
- 如果是其它线程已经持有了该Object的轻量级锁,这时候表明有竞争,进入锁膨胀过程
- 如果是自己执行了synchronized锁重入,那么再添加一条Lock Record作为重入的计数
- 当退出synchronized代码块(解锁)的时候,如果有取值为null的锁记录,表示有重入,这时重置锁记录,表示重入计数减一
- 当推出synchronized代码块(解锁)时,锁记录的值不为null,那么将使用cas将Mark Word的值恢复给对象头
- 成功,则解锁成功
- 失败,说明轻量级锁进行了锁膨胀或已经升级为重量级锁,进入重量级锁解锁流程
重量级锁的实现原理
给一个对象(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实现原理的主要内容,如果未能解决你的问题,请参考以下文章