Mark Word

MarkWord.jpg

锁信息存储在对象头的Mark Word中,在synchronized锁中,这个存储在对象头的Mark Word中的锁信息是一个指针,它指向一个monitor对象(也称为管程或监视器锁)的起始地址。
monitor:(源码在这里)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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;
}

_owner : 当前拥有该 ObjectMonitor 的线程
_EntryList: 当前等待锁的集合
_WaitSet: 调用了Object.wait()方法而进入等待状态的线程的集合

在java中,每一个等待锁的线程都会被封装成ObjectWaiter对象,当多个线程同时访问一段同步代码时,首先会被扔进 _EntryList 集合中,如果其中的某个线程获得了monitor对象,他将成为 _owner,如果在它成为 _owner之后又调用了wait方法,则他将释放获得的monitor对象,进入 _WaitSet集合中等待被唤醒。
这样,我们就通过对象头,将每一个对象与一个monitor关联了起来,它们的关系如下图所示:
fat-lock.png

图片的最左边是线程的调用栈,它引用了堆中的一个对象,该对象的对象头部分记录了该对象所使用的监视器锁,该监视器锁指向了一个monitor对象。

锁的状态

锁一共有四种状态,无锁状态,偏向锁状态,轻量级锁状态和重量级锁状态,它会随着竞争情况逐渐升级。锁可以升级但不能降级,目的是为了提高获得锁和释放锁的效率。
不同锁的比较.jpg
无锁状态 : 对象的HashCode + 对象分代年龄 + 状态位001

参考

线程间的同步与通信(1)——同步代码块Synchronized
线程间的同步与通信(3)——浅析synchronized的实现原理
Java中Synchronized的用法
深入理解多线程(四)—— Moniter的实现原理
OpenJDK9 Hotspot : synchronized 浅析
深入理解Java并发之synchronized实现原理
死磕Java并发—–深入分析synchronized的实现原理
JVM内部细节之一:synchronized关键字及实现细节(轻量级锁Lightweight Locking)
Java中synchronized的实现原理与应用