并发编程(二十五)ObjectMonitor的属性

319 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 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方面需要着重知道的即可,所以列举下面几个重要属性:

  1. header : 重量级锁保存markword的地方

  2. own: 指向我们持有锁的线程;对象的markword里边也保存了指向monitor的指针;

  3. _cxq队列: 竞争队列。 A线程持有锁没有释放; B和C线程同时过来争抢锁,都被block了,此时会将B和C线程加入到 该队列。

  4. EntryList队列:同步队列。A线程释放锁,B和C线程中会选定一个继承者(可以去争抢锁的这个线程),另外一个线程会被放入我们的EntryList队列里边。

  5. 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一起来记忆。

这一章节主要记忆几个重要属性和流程即可。