日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java并发包系列---LockSupport

發(fā)布時間:2024/1/17 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java并发包系列---LockSupport 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

長久以來對線程阻塞與喚醒經常我們會使用object的wait和notify,除了這種方式,java并發(fā)包還提供了另外一種方式對線程進行掛起和恢復,它就是并發(fā)包子包locks提供的LockSupport。

LockSupport提供了park和unpark進行線程的掛起和恢復操作,來看一個簡單掛起和恢復的簡單例子:

由于編輯格式限制,直接貼代碼有人反映會顯得很雜亂,之后有關代碼將直接放圖片,上例子中描述了一個場景,周末了某男興奮的去打游戲了,于是被游戲阻塞了(park),其他的都不干了,這個時候女朋友打來電話,別打游戲了,陪她逛街,把男朋友從游戲中喚醒(unpark)。LockSupport使用方式和wait/notify很類似,LockSupport使用更加靈活,unpark可以先于park進行調用,因為這個特點,我們可以不用擔心掛起和恢復時序問題,就如流打開了必須關閉這中類似問題,給我們帶來很多編程麻煩。

LockSupport底層是有Unsafe提供的兩個基本同步語句,這個在關于Unsafe介紹中已經做了分析,LockSupport是對這兩個函數(shù)的進一步封裝,除了例子中方法,它還提供了其他幾個功能。

以上為LockSupport屬性,Unsafe這個很好理解,整個LockSupport的實現(xiàn)都是基于Unsafe的兩個方法,SEED、PROBE、SECONDARY都是Thread類中為了對象上圖中三個字段的相對地址偏移量,功能主要用于ThreadLocalRandom類進行隨機數(shù)生成,它比Random性能要高的多,可閱讀該篇文章了解詳細(https://my.oschina.net/adan1/blog/159371),雖然LockSupport定義這三個字段但是基本沒有使用,可能之后JDK會有所變化吧。這里parkBlockerOffset字段,解釋起來就是掛起線程對象的偏移地址,對應的是Thread類的parkBlocker。

這個字段可以理解為專門為LockSupport而設計的,它被用來記錄線程是被誰堵塞的,當程序出現(xiàn)問題時候,通過線程監(jiān)控分析工具可以找出問題所在。注釋說該對象被LockSupport的getBlocker和setBlocker來獲取和設置,且都是通過地址偏移量方式獲取和修改的。由于這個變量LockSupport提供了park(Object parkblocker)方法。

代碼很好理解獲取當前線程,通過偏移量的方式設置parkBlocker的值,將調取unsafe.park把線程掛起,線程被恢復后,修改blocker為null。

那我們可以把文章開篇例子修改的更加應景一些,如下:

定義一個blocker者名字叫“游戲”,某男被游戲堵塞park(a),我們通過jstack pid獲取當前線程相關信息(jstack用于打印出給定的Java進程ID或core file或遠程調試服務的Java堆棧信息):

可以看到當前線程狀態(tài)是WAITING,確實通過unsafe.park掛起的,blocker為一個字符串類型的id為0x…的。通過mat工具可以知道這個id對應得對象即為變量名為game的string對象。若不設置blocker,則是空的,如下:

只是將線程進行了掛起,無blocker。

那么LockSupport的park/unpark與wait/notify有啥區(qū)別呢?首先wait/notify對線程所起的作用和park/unpark是一樣的,如下為使用wait阻塞線程的線程狀態(tài):

也是waiting,只是方式是調取Object.wait。說明產生的效果是一樣,那來繼續(xù)分析一下兩者實現(xiàn)機制。

它倆面向操作的對象不同,通過上述分析,我們知道LockSupport阻塞和喚醒線程直接操作的就是線程,所以從語義上講,它更符合常理,或者叫更符合語義。而Object的wait/notify它并不是直接對線程操作,它是被動的方法,它需要一個object來進行線程的掛起或喚醒。

park/unpark使用起來會更加的靈活、方便。在調用對象的wait之前當前線程必須先獲得該對象的監(jiān)視器(synchronized),被喚醒之后需要重新獲取到監(jiān)視器才能繼續(xù)執(zhí)行。而LockSupport則不會,如例子中所示,它可以隨意進行park或者unpark。

兩則雖然都能更改線程狀態(tài)為WAITING,但由于實現(xiàn)的機制不同,所以不會產生交集,就是park掛起線程,notify/notifyall是無法進行喚醒的。我們來看個例子。就好比你在打游戲,一個陌生大媽讓你逛街去,你應該不會去吧(特殊需求的除外)。如下例子(代碼這樣寫也是絕了,僅僅舉例子):

使用notify還有一個問題就是,有時候為了保險起見大多數(shù)都用notifyall,notify只能喚醒一個線程,假如有兩個被阻塞的話,另外一個就悲劇了。

除此之外,park也可以響應中斷異常,關于中斷異常詳講也需要一大篇文章,這里不做詳細分析,來看一下park響應中斷過程。

對開篇代碼改造一下,還是某男打游戲,且深深陷入其中(park),突然屎意甚濃,于是被其中斷(interrupt),然后某男去拉屎去了。最終線程退出了運行,在這里你會發(fā)現(xiàn),park并不會拋出InterruptedException異常。那問題來,不拋出異常,那和正常的unpark有何區(qū)別?不能拉屎中斷和女朋友召喚效果一樣吧。這里就要依賴線程的interruptedstatus,如果線程被中斷而退出阻塞該狀態(tài)會被修改為true。如下可獲取到當前interrupted status。

總結起來LockSupport有以下不同和特點:

  • 其實現(xiàn)機制和wait/notify有所不同,面向的是線程。

  • 不需要依賴監(jiān)視器

  • 與wait/notify沒有交集

  • 使用起來更加靈活方便

  • 總結

    以上是生活随笔為你收集整理的java并发包系列---LockSupport的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內容還不錯,歡迎將生活随笔推薦給好友。