是一个c++类
ObjectMonitor() {
_header = NULL;
_count = 0; //记录个数
_waiters = 0,
_recursions = 0; // 线程重入次数
_object = NULL;
_owner = NULL;
_WaitSet = NULL; // 调用wait方法后的线程会被加入到_WaitSet
_WaitSetLock = 0 ;
_Responsible = NULL ;
_succ = NULL ;
_cxq = NULL ; // 阻塞队列,线程被唤醒后根据决策判读是放入cxq还是EntryList
FreeNext = NULL ;
_EntryList = NULL ; // 没有抢到锁的线程会被放到这个队列
_SpinFreq = 0 ;
_SpinClock = 0 ;
OwnerIsThread = 0 ;
}
ObjectMonitor中有五个重要部分,分别为_ower,_WaitSet,_cxq,_EntryList和count。
_ower 用来指向持有monitor的线程,它的初始值为NULL,表示当前没有任何线程持有monitor。当一个线程成功持有该锁之后会保存线程的ID标识,等到线程释放锁后_ower又会被重置为NULL;
_WaitSet 调用了锁对象的wait方法后的线程会被加入到这个队列中;
_cxq 是一个阻塞队列,线程被唤醒后根据决策判读是放入cxq还是EntryList;
_EntryList 没有抢到锁的线程会被放到这个队列;
count 用于记录线程获取锁的次数,成功获取到锁后count会加1,释放锁时count减1。
当有一个线程获得synchronized锁后,monitor对象中的count就会被加1,并且会将这个线程的id存入到monitor的_ower中。此时,如果其他线程来尝试拿锁则会被放入到_EntryList队列中阻塞。
还记得上一节中我们立的一个Flag了吗?synchronized锁的是container对象,而wait和notify也是container对象的方法,这么一看我们上一节中留下的问题就有些眉目了。是不是调用wait方法的时候线程也会被加入到一个等待队列,而等到notify或者notifyAll的时候再从等待队列中将线程唤醒呢?关于这个问题在这一次,彻底搞懂Java中的synchronized关键字这篇文章中其实已经有解读了,就是调用wait方法的线程会被加入到一个_WaitSet集合中,并会将线程挂起。但是,这里要再次强调一下_WaitSet与_EntryList这两个集合。_EntryList集合中存放的是没有抢到锁,而被阻塞的线程,而_WaitSet集合中存放的是调用了wait方法后,处于等待状态的线程。**
这一次,彻底搞懂Java并发包中的Atomic原子类 - 掘金
这一次,彻底搞懂Java中的ReentrantLockt实现原理 - 掘金
作者:赌一包辣条
链接:https://juejin.cn/post/6973571891915128846
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。