java多線程(核心篇)第三章

第三章

3.1 鎖概述
  1. 鎖的持有線程在其獲得鎖之后和釋放鎖之前這段時間內所執(zhí)行的代碼被稱為臨界區(qū)戈鲁。
  2. Java平臺中的鎖包括內部鎖和顯示鎖。內部鎖是通過synchronized關鍵字實現(xiàn)的嘹叫;顯示鎖是通過Lock接口的實現(xiàn)類實現(xiàn)的婆殿。
  3. 可見性的保障是通過寫線程沖刷處理器緩存和讀線程刷新處理器緩存這兩個動作實現(xiàn)的。鎖的獲得隱含著刷新處理器緩存這個動作待笑,這使得讀線程在執(zhí)行臨界區(qū)代碼前(獲得鎖之后)可以將寫線程對共享變量所做的更新同步到該線程執(zhí)行處理器的高速緩存中鸣皂;而鎖的釋放隱含著沖刷處理器緩存這個動作。
  4. 鎖對可見性暮蹂、原子性和有序性的保障是有條件的:
    • 這些線程在訪問同一組共享數(shù)據的時候必須使用同一個鎖寞缝。
    • 這些線程中的任意一個線程,即使其僅僅是讀取這組共享數(shù)據而沒有對其進行更新的話仰泻,也需要在讀取時持有相應的鎖荆陆。
  5. 一個線程在其持有一個鎖的時候能否再次(或者多次)申請該鎖。如果一個線程持有一個鎖的時候還能夠繼續(xù)成功申請該鎖集侯,那么我們就稱該鎖是可重入的被啼。
  6. Java平臺中鎖的調度策略也包括公平策略和非公平策略,相應的鎖就被稱為公平鎖和非公平鎖棠枉。
  7. 一個鎖實例所保護的共享數(shù)據的數(shù)量大小就被稱為該鎖的粒度浓体。
3.2 內部鎖:synchronized關鍵字
image.png
  1. synchronized 關鍵字修飾的代碼塊被稱為同步塊。
  2. 作為鎖句柄的變量通常采用final修飾辈讶,鎖不能改變命浴。通常會使用private修飾作為鎖句柄的變量。
  3. 同步靜態(tài)方法相當于以當前類對象為引導鎖的同步塊贱除。
  4. 公平鎖保障鎖調度的公平性往往是以增加了線程的暫停和喚醒的可能性生闲,即增加了上下文切換為代價的。因此月幌,公平鎖適合于鎖被持有的時間相對長或者線程申請鎖的平均間隔時間相對長的情形碍讯。
  5. 使用顯示鎖的時候必須注意將鎖的釋放操作放在finally塊中
  6. Lock接口定義了一個tryLock扯躺。該方法的作用是嘗試申請相應Lock實例鎖標識的鎖捉兴。避免出現(xiàn)持有線程一直不釋放鎖這個鎖(例如代碼錯誤),同步在該鎖之上的所有線程就會一直被暫停而使其任務無法進展录语。
image.png
  1. 改進型鎖:讀寫鎖
    • 讀寫鎖允許多個線程可以同時讀戎崾酢(只讀)共享變量,但是一次只允許一個線程對共享變量進行更新(包括讀取后再更新)钦无。
    • 任何一個線程持有一個讀鎖的時候逗栽,其他任何線程都無法獲得相應鎖的寫鎖。
    • 讀寫鎖適用于
      • 只讀操作比寫(更新)操作要頻繁得多失暂。
      • 讀線程持有鎖的時間比較長彼宠。
3.3 輕量級同步機制:volatile關鍵字
  1. volatile關鍵字用于修飾共享可變變量鳄虱,即沒有使用final關鍵字修飾的實例變量或靜態(tài)變量
  2. volatile變量不會被編譯器分配到寄存器進行存儲凭峡,對volatile變量的讀寫操作都是內存訪問(訪問高速緩存相當于主內存)操作拙已。
  3. volatile關鍵字的作用包括:保障可見性、保障有序性和保障long/double型變量讀寫操作的原子性摧冀。
  4. 一般而言倍踪,對volatile變量的賦值操作,其右邊表達式中只要涉及共享變量(包括被賦值的volatiel變量本身)索昂,那么這個賦值操作就不是原子操作建车。
  5. 如果被修飾的變量是個數(shù)組,那么volatile關鍵字只能夠對數(shù)組引用本身的操作(讀取數(shù)組引用和更新數(shù)組引用)起作用椒惨,而無法對數(shù)組元素的操作(讀取缤至、更新數(shù)組元素)起作用。
  6. volatile應用場景
    • 使用volatile變量作物狀態(tài)標志康谆。在該場景中领斥,應用程序的某個狀態(tài)由一個線程設置,其他線程會讀取該狀態(tài)并以該狀態(tài)作為其計算的依據(或者僅僅讀取并輸出這個狀態(tài)值)沃暗。此時使用volatile變量作為同步機制的好處是一個線程能夠“通知”另外一個線程某種事件(例如月洛,網絡連接斷連之后重新連上)的發(fā)生,而這些線程又無須因此而使用鎖孽锥。從而避免了鎖的開銷以及相關問題嚼黔。
    • 使用volatile保障可見性。其中一個線程更新了該變量之后忱叭,其他線程無須加鎖的情況下也能夠看到更新隔崎。
    • 使用volatile變量替代鎖今艺。利用volatile變量寫操作具有的原子性韵丑,可以把一組可變狀態(tài)變量封裝成一個對象,那么對這些狀態(tài)變量的更新操作就可以通過創(chuàng)建一個新的對象并將該對象引用賦值給相應的引用型變量來實現(xiàn)虚缎。volatile適合于多個線程共享一個狀態(tài)變量(對象)撵彻,而鎖更實用用于多個線程共享一組狀態(tài)變量。
    • 使用volatile實現(xiàn)簡易版讀寫鎖实牡。
      image.png
3.4 對象的發(fā)布與逸出
  1. 對象發(fā)布形式

    • 將對象引用存儲到public變量中陌僵。
    • 在非private方法(包括public、protected创坞、package方法)中返回一個對象碗短。
    • 創(chuàng)建內部類,使得當前對象(this)能夠被這個內部類使用题涨。
    • 通過方法調用將對象傳遞給外部方法偎谁。
  2. 對象初始化安全:final與static

    2.1 static

    • java中類的初始化實際上也采取了延遲加載的技術总滩,即一個類被java虛擬機加載之后,該類的所有靜態(tài)變量的值仍然是其默認值(引用型變量的默認值為null,boolean變量的默認值為false),直到有個線程初次訪問了該類的任意一個靜態(tài)變量才使這個類被初始化——類的靜態(tài)初始塊("static{}")被執(zhí)行巡雨,類的所有靜態(tài)變量被賦予初始化闰渔。
    • static關鍵字僅僅保障讀線程能夠讀取到相應字段的初始值,而不是相對新值铐望。

    2.2 final

    • 當一個對象被發(fā)布到其他線程的時候冈涧,該對象的所有final字段(實例變量)都是初始化完畢的,即其他線程讀取這些字段的時候所讀取到的值都是相應字段的初始值(而不是默認值)正蛙。而非final字段沒有這種保障督弓,即這些線程讀取該對象的非final字段時所讀取到的值可能仍然是相應字段的默認值。
3.5 對象逸出
  1. 容易導致對象逸出的幾種形式

    • 在構造器中將this賦值給一個共享變量跟畅。
    • 在構造器中將this作為方法參數(shù)傳遞給其他方法咽筋。
    • 在構造器中啟動基于匿名類的線程。(其他線程可能看到的是一個未初始化完成的對象)
  2. 一般地徊件,如果一個類需要創(chuàng)建自己的工作者線程奸攻,那么我們可以為該類定義一個init方法(可以是private的),相應的工作者線程可以在該方法或者該類的構造器創(chuàng)建虱痕,但是線程的啟動則是在init方法中執(zhí)行的睹耐。


    image.png
  3. 開銷大小

    • 使用static關鍵字修飾引用該對象的變量。
    • 使用final關鍵字修飾引用該對象的變量部翘。
    • 使用volatile關鍵字修飾引用該對象的變量硝训。
    • 使用AtomicReference來引用該對象。
    • 對訪問該對象的代碼進行加鎖新思。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末窖梁,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子夹囚,更是在濱河造成了極大的恐慌纵刘,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件荸哟,死亡現(xiàn)場離奇詭異假哎,居然都是意外死亡,警方通過查閱死者的電腦和手機鞍历,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進店門舵抹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人劣砍,你說我怎么就攤上這事惧蛹。” “怎么了?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵香嗓,是天一觀的道長爵政。 經常有香客問我,道長陶缺,這世上最難降的妖魔是什么钾挟? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮饱岸,結果婚禮上掺出,老公的妹妹穿的比我還像新娘。我一直安慰自己苫费,他們只是感情好汤锨,可當我...
    茶點故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著百框,像睡著了一般闲礼。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上铐维,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天柬泽,我揣著相機與錄音,去河邊找鬼嫁蛇。 笑死锨并,一個胖子當著我的面吹牛,可吹牛的內容都是我干的睬棚。 我是一名探鬼主播第煮,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼抑党!你這毒婦竟也來了包警?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤底靠,失蹤者是張志新(化名)和其女友劉穎害晦,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體苛骨,經...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡篱瞎,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年苟呐,在試婚紗的時候發(fā)現(xiàn)自己被綠了痒芝。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,424評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡牵素,死狀恐怖严衬,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情笆呆,我是刑警寧澤请琳,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布粱挡,位于F島的核電站,受9級特大地震影響俄精,放射性物質發(fā)生泄漏询筏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一竖慧、第九天 我趴在偏房一處隱蔽的房頂上張望嫌套。 院中可真熱鬧,春花似錦圾旨、人聲如沸踱讨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽痹筛。三九已至,卻和暖如春廓鞠,著一層夾襖步出監(jiān)牢的瞬間帚稠,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工床佳, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留翁锡,地道東北人。 一個月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓夕土,卻偏偏與公主長得像馆衔,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子怨绣,可洞房花燭夜當晚...
    茶點故事閱讀 45,435評論 2 359