开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第23天,点击查看活动详情
1.ObjectMonitor的属性
//ObjectMonitor在C++中结构体如下
ObjectMonitor::ObjectMonitor() {
_header = NULL;
_count = 0;
_waiters = 0,
_recursions = 0; //线程的重入次数
_object = NULL;
_owner = NULL; //标识拥有该monitor的线程
_WaitSet = NULL; //等待线程组成的双向循环链表,_WaitSet是第一个节点
_WaitSetLock = 0 ;
_Responsible = NULL ;
_succ = NULL ;
_cxq = NULL ; //多线程竞争锁进入时的单向链表
FreeNext = NULL ;
_EntryList = NULL ; //_owner从该双向循环链表中唤醒线程结点,_EntryList是第一个节点
_SpinFreq = 0 ;
_SpinClock = 0 ;
OwnerIsThread = 0 ;
}
因为里面主要是C++,我们主要是讲java方面需要着重知道的即可,所以列举下面几个重要属性:
-
header : 重量级锁保存markword的地方
-
own: 指向我们持有锁的线程;对象的markword里边也保存了指向monitor的指针;
-
_cxq队列: 竞争队列。 A线程持有锁没有释放; B和C线程同时过来争抢锁,都被block了,此时会将B和C线程加入到 该队列。
-
EntryList队列:同步队列。A线程释放锁,B和C线程中会选定一个继承者(可以去争抢锁的这个线程),另外一个线程会被放入我们的EntryList队列里边。
-
waitset:等待队列。Object wait的线程。
流程:
A线程持有锁,BC线程过来竞争失败,进入cxq -- 下轮竞争会把 cxq里的线程移动到EntrylIst中,C线程没有竞争到进入了EntryList队列中。假设B线程竞争到了锁,然后B线程调用了 Object.Wait方法,这时候B线程进入waitset,并释放锁。C线程拿到了锁,然后唤醒B线程。B线程会从waitset里边出来,直接竞争锁。如果竞争失败进入cxq,继续轮回,如果竞争成功,ok了。
2.其他
这一部分跟以后讲到的lock相关的内容非常相似,以后讲到lock希望能对比ObjectMonitor一起来记忆。
这一章节主要记忆几个重要属性和流程即可。