java并發(fā)編程之LockSupport

LockSupport运吓,構(gòu)建同步組件的基礎(chǔ)工具渴邦,幫AQS完成相應(yīng)線程的阻塞或者喚醒的工作。

LockSupport源碼分析

LockSupport定義了一組以park開(kāi)頭的方法來(lái)阻塞當(dāng)前線程拘哨,unpark來(lái)喚醒被阻塞的線程谋梭。

阻塞線程

  • park()實(shí)現(xiàn)
public static void park() {
    UNSAFE.park(false, 0L);
}

調(diào)用native方法阻塞當(dāng)前線程。

  • parkNanos(long nanos)實(shí)現(xiàn)
public static void parkNanos(long nanos) {
    if (nanos > 0)
        UNSAFE.park(false, nanos);
}

阻塞當(dāng)前線程宅静,最長(zhǎng)不超過(guò)nanos納秒章蚣,返回條件在park()的基礎(chǔ)上增加了超時(shí)返回。

  • parkUntil(long deadline)實(shí)現(xiàn)
public static void parkUntil(long deadline) {
    UNSAFE.park(true, deadline);
}

阻塞當(dāng)前線程姨夹,知道deadline時(shí)間(deadline - 毫秒數(shù))纤垂。

在java6之后在park系列方法新增加了入?yún)?code>Object blocker,用于標(biāo)識(shí)阻塞對(duì)象磷账,該對(duì)象主要用于問(wèn)題排查和系統(tǒng)監(jiān)控峭沦。

  • park(Object blocker)實(shí)現(xiàn)
public static void park(Object blocker) {
    Thread t = Thread.currentThread();
    setBlocker(t, blocker);
    UNSAFE.park(false, 0L);
    setBlocker(t, null);
}
  • 記錄當(dāng)前線程等待的對(duì)象(阻塞對(duì)象);

  • 阻塞當(dāng)前線程逃糟;

  • 當(dāng)前線程等待對(duì)象置為null吼鱼。

  • parkNanos(Object blocker, long nanos)實(shí)現(xiàn)

public static void parkNanos(Object blocker, long nanos) {
    if (nanos > 0) {
        Thread t = Thread.currentThread();
        setBlocker(t, blocker);
        UNSAFE.park(false, nanos);
        setBlocker(t, null);
    }
}

阻塞當(dāng)前線程,最長(zhǎng)等待時(shí)間不超過(guò)nanos毫秒绰咽,同樣菇肃,在阻塞當(dāng)前線程的時(shí)候做了記錄當(dāng)前線程等待的對(duì)象操作。

  • parkUntil(Object blocker, long deadline)
public static void parkUntil(Object blocker, long deadline) {
    Thread t = Thread.currentThread();
    setBlocker(t, blocker);
    UNSAFE.park(true, deadline);
    setBlocker(t, null);
}

阻塞當(dāng)前線程直到deadline時(shí)間取募,相同的琐谤,也做了阻塞前記錄當(dāng)前線程等待對(duì)象的操作。

到這里玩敏,問(wèn)題來(lái)了斗忌,為什么在java6要在入?yún)⒁隻locker呢?blocker的作用到底是什么旺聚?

先看看線程dump的結(jié)果:


線程dump結(jié)果對(duì)比

從線程dump結(jié)果可以看出:
有blocker的可以傳遞給開(kāi)發(fā)人員更多的現(xiàn)場(chǎng)信息织阳,可以查看到當(dāng)前線程的阻塞對(duì)象,方便定位問(wèn)題砰粹。所以java6新增加帶blocker入?yún)⒌南盗衟ark方法唧躲,替代原有的park方法。

喚醒線程

  • unpark(Thread thread)實(shí)現(xiàn)
public static void unpark(Thread thread) {
    if (thread != null)
        UNSAFE.unpark(thread);
}

喚醒處于阻塞狀態(tài)的線程Thread。

從源碼不難發(fā)現(xiàn)惊窖,LockSupport所有的方法都是調(diào)用native的park和unpark實(shí)現(xiàn)的刽宪,接下來(lái)我們具體看看HotSpot中的park/unpark的具體實(shí)現(xiàn)。

HotSpot里的park/unpark

在HotSpot中界酒,每個(gè)java線程都有一個(gè)Parker的實(shí)例圣拄,Parker的定義是這樣子的:


Parker定義

從Parker定義不難看出:

  1. 定義私有屬性_counter:可以理解為是否可以調(diào)用park的一個(gè)許可證,只有_count > 0的時(shí)候才能調(diào)用毁欣;

  2. 提供public方法park和unpark支撐阻塞/喚醒線程庇谆;

  3. Parker繼承PlatformParker:


    PlatformParker定義

    從PlatformParker的定義可以看出,Parker實(shí)際上是利用Posix的mutex凭疮,condition來(lái)實(shí)現(xiàn)的饭耳。

HotSpot park實(shí)現(xiàn)

  1. 嘗試是否能可以調(diào)用park,如果_counter > 0执解,可以調(diào)用寞肖,將_counter置為0,返回衰腌;


    park步驟1具體實(shí)現(xiàn)
  2. 步驟1不成功新蟆,構(gòu)造當(dāng)前線程的ThreadBlockInVM,檢查_(kāi)counter > 0是否成立右蕊,成立則將_counter設(shè)置為0琼稻,unlock mutex,返回饶囚;


    park步驟2具體實(shí)現(xiàn)
  3. 步驟2不成功帕翻,根據(jù)等待時(shí)間調(diào)用不同的等待函數(shù)等待,如果等待返回正確萝风,將_counter置為0嘀掸,unlock mutex,返回规惰,park調(diào)用成功横殴。


    park步驟3具體實(shí)現(xiàn)

相比之下,unpark的實(shí)現(xiàn)就簡(jiǎn)單多了卿拴。

HotSpot unpark實(shí)現(xiàn)

unpark實(shí)現(xiàn)

  1. 將_counter置為1;
  2. 判斷之前_counter的值:
  • 小于1時(shí)梨与,調(diào)用pthread_cond_signal喚醒在park中等待的線程堕花;
  • 等于1時(shí),unlock mutex粥鞋,返回缘挽。

總結(jié):HotSpot Parker用condition和mutex維護(hù)了一個(gè)_counter變量,park時(shí),變量_counter置為0壕曼,unpark時(shí)苏研,變量_counter置為1。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末腮郊,一起剝皮案震驚了整個(gè)濱河市摹蘑,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌轧飞,老刑警劉巖衅鹿,帶你破解...
    沈念sama閱讀 218,858評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異过咬,居然都是意外死亡大渤,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)掸绞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)泵三,“玉大人,你說(shuō)我怎么就攤上這事衔掸√棠唬” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,282評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵具篇,是天一觀的道長(zhǎng)纬霞。 經(jīng)常有香客問(wèn)我,道長(zhǎng)驱显,這世上最難降的妖魔是什么诗芜? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,842評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮埃疫,結(jié)果婚禮上伏恐,老公的妹妹穿的比我還像新娘。我一直安慰自己栓霜,他們只是感情好翠桦,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著胳蛮,像睡著了一般销凑。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上仅炊,一...
    開(kāi)封第一講書(shū)人閱讀 51,679評(píng)論 1 305
  • 那天斗幼,我揣著相機(jī)與錄音,去河邊找鬼抚垄。 笑死蜕窿,一個(gè)胖子當(dāng)著我的面吹牛谋逻,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播桐经,決...
    沈念sama閱讀 40,406評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼毁兆,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了阴挣?” 一聲冷哼從身側(cè)響起气堕,我...
    開(kāi)封第一講書(shū)人閱讀 39,311評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎屯吊,沒(méi)想到半個(gè)月后送巡,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,767評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡盒卸,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年骗爆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蔽介。...
    茶點(diǎn)故事閱讀 40,090評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡摘投,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出虹蓄,到底是詐尸還是另有隱情犀呼,我是刑警寧澤,帶...
    沈念sama閱讀 35,785評(píng)論 5 346
  • 正文 年R本政府宣布薇组,位于F島的核電站外臂,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏律胀。R本人自食惡果不足惜宋光,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望炭菌。 院中可真熱鬧罪佳,春花似錦、人聲如沸黑低。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,988評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)克握。三九已至蕾管,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間菩暗,已是汗流浹背娇掏。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,101評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留勋眯,地道東北人婴梧。 一個(gè)月前我還...
    沈念sama閱讀 48,298評(píng)論 3 372
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像客蹋,于是被迫代替她去往敵國(guó)和親塞蹭。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容