天天看點

【Java并發程式設計實戰】----- AQS(三):阻塞、喚醒:LockSupport

在上篇部落格(【Java并發程式設計實戰】----- AQS(二):擷取鎖、釋放鎖)中提到,當一個線程加入到CLH隊列中時,如果不是頭節點是需要判斷該節點是否需要挂起;在釋放鎖後,需要喚醒該線程的繼任節點

lock方法,在調用acquireQueued():

在acquireQueued()中調用parkAndCheckInterrupt()來挂起目前線程:

調用LockSupport.park()方法。對于park():為了線程排程,在許可可用之前禁用目前線程。

釋放鎖後,需要喚醒該線程繼任節點:

在release方法中調用unparkSuccessor()來喚醒該線程的繼任節點。在unparkSuccessor()方法中通過LockSupport.unpark()來喚醒。unpark():如果給定線程的許可尚不可用,則使其可用。

LockSupport是用來建立鎖和其他同步類的基本線程阻塞原語。每個使用LockSupport的線程都會與一個許可關聯,如果該許可可用,并且可在程序中使用,則調用park()将會立即傳回,否則可能阻塞。如果許可尚不可用,則可以調用 <code>unpark</code> 使其可用。但是注意許可不可重入,也就是說隻能調用一次park()方法,否則會一直阻塞。

LockSupport.park()、LockSupport.unpark()的作用分别是阻塞線程和解除阻塞線程,且park()和unpark()不會遇到“Thread.suspend ()和 Thread.resume所可能引發的死鎖”問題。當然park()、unpark()是成對使用。

park():如果許可可用,則使用該許可,并且該調用立即傳回;否則,為線程排程禁用目前線程,并在發生以下三種情況之一以前,使其處于休眠狀态:

其他某個線程将目前線程作為目标調用 <code>unpark</code>;或者

其他某個線程中斷目前線程;或者

該調用不合邏輯地(即毫無理由地)傳回。

其源碼實作如下:

unpark:如果給定線程的許可尚不可用,則使其可用。如果線程在 park 上受阻塞,則它将解除其阻塞狀态。否則,保證下一次調用 park 不會受阻塞。如果給定線程尚未啟動,則無法保證此操作有任何效果。

其源代碼如下:

一般來說park()、unpark()是成對出現的,同時unpark必須要在park執行之後執行,當然并不是說沒有不調用unpark線程就會一直阻塞,park有一個方法,它帶了時間戳(parkNanos(long nanos):為了線程排程禁用目前線程,最多等待指定的等待時間,除非許可可用。)

參考資料

1、LockSupport的park和unpark的基本使用,以及對線程中斷的響應性

PS:如果你覺得文章對你有所幫助,别忘了推薦或者分享,因為有你的支援,才是我續寫下篇的動力和源泉!

作者:chenssy。一個專注于【死磕 Java】系列創作的男人

出處:https://www.cnblogs.com/chenssy/p/5079724.html

作者個人網站:https://www.cmsblogs.com/。專注于 Java 優質系列文章分享,提供一站式 Java 學習資料

目前死磕系列包括:

    1. 【死磕 Java 并發】:https://www.cmsblogs.com/category/1391296887813967872(已完成)

    2.【死磕 Spring 之 IOC】:https://www.cmsblogs.com/category/1391374860344758272(已完成)

    3.【死磕 Redis】:https://www.cmsblogs.com/category/1391389927996002304(已完成)

    4.【死磕 Java 基礎】:https://www.cmsblogs.com/category/1411518540095295488

    5.【死磕 NIO】:https://www.cmsblogs.com/article/1435620402348036096

本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接,否則保留追究法律責任的權利。