关于 synchronize 加解锁

加锁过程

到这里我们已经把线程C在BLOCK的时候的逻辑理清楚了,小结如下:

偏向锁逻辑,未命中;
如果是无锁状态,就通过CAS去竞争锁,此处由于锁已经被线程B持有,所以不是无锁状态;
不是无锁状态,而且锁不是线程C持有,执行锁膨胀,构造OjectMonitor对象;
竞争锁,竞争失败就将线程加入_cxq队列的首位;
开始无限循环,竞争锁成功就退出循环,竞争失败线程挂起,等待被唤醒后继续竞争;

解锁过程

偏向锁逻辑,此处未命中;
根据QMode的不同,将ObjectWaiter从_cxq或者_EntryList中取出后唤醒;
QMode = 2,并且_cxq非空:取_cxq队列排头位置的ObjectWaiter对象,调用ExitEpilog方法,该方法会唤醒ObjectWaiter对象的线程,此处会立即返回,后面的代码不会执行了;
QMode = 3,并且_cxq非空:把_cxq队列首元素放入_EntryList的尾部;
QMode = 4,并且_cxq非空:把_cxq队列首元素放入_EntryList的头部;
QMode = 0,不做什么,继续往下看;
如果_EntryList的首元素非空,就取出来调用ExitEpilog方法,该方法会唤醒ObjectWaiter对象的线程,然后立即返回;
如果_EntryList的首元素为空,就取_cxq的首元素,放入_EntryList,然后再从_EntryList中取出来执行ExitEpilog方法,然后立即返回;
只有QMode=2的时候会提前返回,等于0、3、4的时候都会继续往下执行:
唤醒的元素会继续执行挂起前的代码,按照我们之前的分析,线程唤醒后,就会通过CAS去竞争锁,此时由于线程B已经释放了锁,那么此时应该能竞争成功;

https://blog.csdn.net/boling_cavalry/article/details/77793224

posted @ 2021-08-09 21:29  TomStudio  阅读(117)  评论(0)    收藏  举报