checkInterruptWhileWaiting
如果當(dāng)前線程被中斷,則調(diào)用transferAfterCancelledWait方法判斷后續(xù)的處理應(yīng)該是拋出InterruptedException還是重新中斷。
這里需要注意的地方是,如果第一次CAS失敗了,則不能判斷當(dāng)前線程是先進(jìn)行了中斷還是先進(jìn)行了signal方法的調(diào)用,可能是先執(zhí)行了signal然后中斷,也可能是先執(zhí)行了中斷,后執(zhí)行了signal,當(dāng)然,這兩個(gè)操作肯定是發(fā)生在CAS之前。這時(shí)需要做的就是等待當(dāng)前線程的node被添加到AQS隊(duì)列后,也就是enq方法返回后,返回false告訴checkInterruptWhileWaiting方法返回REINTERRUPT(1),后續(xù)進(jìn)行重新中斷。
簡(jiǎn)單來說,該方法的返回值代表當(dāng)前線程是否在park的時(shí)候被中斷喚醒,如果為true表示中斷在signal調(diào)用之前,signal還未執(zhí)行,那么這個(gè)時(shí)候會(huì)根據(jù)await的語義,在await時(shí)遇到中斷需要拋出interruptedException,返回true就是告訴checkInterruptWhileWaiting返回THROW_IE(-1)。
如果返回false,否則表示signal已經(jīng)執(zhí)行過了,只需要重新響應(yīng)中斷即可
private int checkInterruptWhileWaiting(Node node) { return Thread.interrupted() ? (transferAfterCancelledWait(node) ? THROW_IE : REINTERRUPT) :0; } final boolean transferAfterCancelledWait(Node node) {//使用cas修改節(jié)點(diǎn)狀態(tài),如果還能修改成功,說明線程被中斷時(shí),signal還沒有被調(diào)用。 // 這里有一個(gè)知識(shí)點(diǎn),就是線程被喚醒,并不一定是在java層面執(zhí)行了locksupport.unpark,也可能是調(diào)用了線程的interrupt()方法,這個(gè)方法會(huì)更新一個(gè)中斷標(biāo)識(shí),并且會(huì)喚醒處于阻塞狀態(tài)下的線程。 if (compareAndSetWaitStatus(node, Node.CONDITION, 0)) { enq(node); //如果cas成功,則把node添加到AQS隊(duì)列 return true; } //如果cas失敗,則判斷當(dāng)前node是否已經(jīng)在AQS隊(duì)列上,如果不在,則讓給其他線程執(zhí)行 //當(dāng)node被觸發(fā)了signal方法時(shí),node就會(huì)被加到 aqs隊(duì)列上 while (!isOnSyncQueue(node))//循環(huán)檢測(cè)node是否已經(jīng)成功添加到AQS隊(duì)列中。如果沒有,則通過yield, Thread.yield(); return false; }?
總結(jié)
以上是生活随笔為你收集整理的checkInterruptWhileWaiting的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 被阻塞的线程唤醒后的逻辑
- 下一篇: acquireQueued