深入分析synchronized的实现原理
实现原理
synchronized
可以保证方法或者代码块在运行时,同一时刻只有一个方法可以进入到临界区,同时它还可以保证共享变量的内存可见性。
Java 中每一个对象都可以作为锁,这是 synchronized
实现同步的基础:
- 普通同步方法,锁是当前实例对象
- 静态同步方法,锁是当前类的 Class 对象
-
同步方法块,锁是括号里面的对象
- 1)同步代码块是使用
monitorenter
和monitorexit
指令实现的; - 2)同步方法依靠的是方法修饰符上的
ACC_SYNCHRONIZED
实现。 - 同步代码块:
monitorenter
指令插入到同步代码块的开始位置,monitorexit
指令插入到同步代码块的结束位置,JVM 需要保证每一个monitorenter
都有一个monitorexit
与之相对应。任何对象都有一个 Monitor 与之相关联,当且一个 Monitor 被持有之后,他将处于锁定状态。线程执行到monitorenter
指令时,将会尝试获取对象所对应的 Monitor 所有权,即尝试获取对象的锁。
Java对象头
对象由多部分构成的,对象头,属性字段、补齐区域等。所谓补齐区域是指如果对象总大小不是4字节的整数倍,会填充上一段内存地址使之成为整数倍。
对象头这部分在对象的最前端,包含两部分或者三部分:Mark Word
(标记字段)和 Klass Pointer
(类型指针) ,如果对象是一个数组,那么还可能包含第三部分:数组的长度。
Klass Pointer
是是对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例。
Mark Word
用于存储对象自身的运行时数据,主要包含对象的哈希值、年龄分代、锁标志位等,大小为32位或64位,当对象处于不同的锁状态时,它的Mark Word里的东西会被替换成不同东西,如下表所示:
Monitor
什么是Monitor?
- 1.Monitor是一种用来实现同步的工具
- 2.与每个java对象相关联,即每个java对象都有一个Monitor与之对应
- 3.Monitor是实现Sychronized(内置锁)的基础
ObjectMonitor
在HotSpot虚拟机中,monitor采用ObjectMonitor
实现。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class ObjectMonitor {
// initialize the monitor, exception the semaphore, all other fields
// are simple integers or pointers
ObjectMonitor() {
_header = NULL;
_count = 0;
_waiters = 0,
_recursions = 0;
_object = NULL;
_owner = NULL;
_WaitSet = NULL;
_WaitSetLock = 0 ;
_Responsible = NULL ;
_succ = NULL ;
_cxq = NULL ;
FreeNext = NULL ;
_EntryList = NULL ;
_SpinFreq = 0 ;
_SpinClock = 0 ;
OwnerIsThread = 0 ;
_previous_owner_tid = 0;
}
}
ObjectMonitor
对象中有两个队列:_WaitSet 和 _EntryList,用来保存ObjectWaiter
对象列表;_owner指向获得ObjectMonitor
对象的线程。
_WaitSet
:处于wait状态的线程,会被加入到wait set;
_EntryList
:处于等待锁block状态的线程,会被加入到entryList;
jdk源码剖析二: 对象内存布局、synchronized终极原理
关于synchronized的Monitor Object机制的研究