5 7 10 any
10 13 10 any
这两者虽然显示效果不同,但他们都是经过 monitor 来完成同步的。
其中在Java虚拟机(HotSpot)中,Monitor是由ObjectMonitor完成的,其主要数据结构如下(位于HotSpot虚拟机源码ObjectMonitor.hpp文件,C++完成的):
ObjectMonitor() {
_header = NULL;
_count = 0; // 用来记载该对象被线程获取锁的次数,这也阐明了synchronized是可重入的
_waiters = 0,
_recursions = 0;
_object = NULL;
_owner = NULL; // 指向持有ObjectMonitor对象的线程
_WaitSet = NULL; // 处于wait形状的线程,会被参加到_WaitSet,调用了wait办法之后会进入这里
_WaitSetLock = 0 ;
_Responsible = NULL ;
_succ = NULL ;
_cxq = NULL ;
FreeNext = NULL ;
_EntryList = NULL ; // 处于等候锁block形状的线程,会被参加到该列表
_SpinFreq = 0 ;
_SpinClock = 0 ;
OwnerIsThread = 0 ;
}
每个 Java 对象在 JVM 的对等对象的头中保存锁形状,指向 ObjectMonitor。
ObjectMonitor 保存了以后持有锁的线程援用,EntryList 中保存目前等候获取锁的线程,WaitSet 保存 wait 的线程。
还有一个计数器count,每当线程取得 monitor 锁,计数器 +1,当线程重入此锁时,计数器还会 +1。当计数器不为 0 时,其它尝试获取 monitor 锁的线程将会被保存到EntryList中,并被阻塞。
当持有锁的线程释放了monitor 锁后,计数器 -1。当计数器归位为 0 时,一切 EntryList 中的线程会尝试去获取锁,但只会有一个线程会成功,没有成功的线程依旧保存在 EntryList 中。
(责任编辑:admin)