《深入理解Java虛擬機》筆記--線程安全與鎖優(yōu)化

1.線程安全

如果不用考慮這些線程在運行時環(huán)境下的調(diào)度和交替執(zhí)行显押,也不需要進行額外的同步,或者在調(diào)用方進行任何其他的協(xié)調(diào)操作包券,調(diào)用這個對象的行為都可以獲得正確的結(jié)果首妖,那這個對象是線程安全的。(要求代碼本身封裝好了保障手段塔次,令調(diào)用者無需關(guān)心多線程的問題方篮,更無需自己采取任何措施保障線程安全)

1.1Java語言中的線程安全

按照線程的“安全程序”由強至弱劃分,可以分為5類

  1. 不可變
    如果一個不可變的對象創(chuàng)建了(例如被final修飾)励负,那不管哪個線程看到的永遠都是一個值恭取,自然就是線程安全的。
    String的substring()replace()等方法都不會影響他原來的值熄守,只是返回一個新構(gòu)造的字符串對象
    2.絕對線程安全
    絕對線程安全將是最上面定義的內(nèi)容蜈垮,但是通常沒有絕對線程安全。
    比如一些常說的線程安全的類裕照,如Vector是一個線程安全的容器攒发,因為內(nèi)部的add(),get()方法都是被synchronized修飾的。但是仍然要在方法調(diào)用端做額外的同步措施
  2. 相對線程安全
    這個就是普遍說的線程安全晋南,比如Vector,HashTable
  3. 線程兼容
    線程兼容指對象本身并不是線程安全的惠猿,但是可以通過正確的調(diào)用手段來保障對象并發(fā)環(huán)境中可以安全的使用,例如 ArrayList,HashMap
  4. 線程對立
    無論調(diào)用端怎么做都無法保障線程安全

1.2線程安全的實現(xiàn)方法

1.2.1互斥同步(阻塞同步)

同步是指多個線程并發(fā)訪問共享數(shù)據(jù)時负间,保證共享數(shù)據(jù)在同一個時刻只被一個(或者是一些偶妖,使用信號量時)線程使用。而互斥是實現(xiàn)同步的一種手段政溃,互斥鎖方法趾访,同步是目的
最基本的互斥手段是使用synchronized

  • synchronized關(guān)鍵字經(jīng)過編譯后,會在同步代碼塊的前后分別形成monitorenter和monitorexit這兩個字節(jié)碼指令(XXXenter和XXXexit這樣就好記了)董虱,這兩個字節(jié)碼都需要一個reference類型的參數(shù)來指明要鎖定和解鎖的對象扼鞋。
  • 如果Java程序中的synchronized明確指定了對象參數(shù)申鱼,那就算這個對象的reference;如果沒有明確指定云头,那家根據(jù)synchronized修飾的是實例方法還是類方法捐友,去取對于的對象實例或Class對象作為鎖對象
  • 根據(jù)虛擬機規(guī)范要求,在執(zhí)行monitorenter指令時溃槐,首先要嘗試獲取對象的鎖匣砖。如果這個對象沒有被鎖,或當前線程已經(jīng)擁有了那個對象的鎖昏滴,就把鎖的計數(shù)器加1脆粥,相應(yīng)的,在執(zhí)行monitorexit指令時會將鎖計數(shù)器減1影涉,當計數(shù)器值為0時变隔,鎖就被釋放。如果獲取對象鎖失敗蟹倾,那么當前線程就要阻塞等待匣缘,直到對象鎖被另外一個線程釋放為止
  • synchronized同步塊對同一條線程來說是可重入的,不會出現(xiàn)自己把自己瑣死的問題鲜棠。同步快在已進入的線程執(zhí)行完之前肌厨,會阻塞后面其他線程的進入。
  • synchronized雖然看起來是“萬能”的豁陆,但不建議濫用的原因是因為消耗大柑爸。因為Java線程是映射到操作系統(tǒng)原生線程的,如果要阻塞或喚醒一個線程都需要原生線程幫忙完成盒音,這就需要從用戶態(tài)轉(zhuǎn)換到核心態(tài)中表鳍,因此狀態(tài)轉(zhuǎn)換需要耗費很多的處理器時間,所以 synchronized是Java語言中的一個重量級操作

除了synchronized之外祥诽,java.util.concurrent包下的重入鎖(ReentrantLock)來
實現(xiàn)同步譬圣,重入鎖多了一些高級功能:等待可中斷、可實現(xiàn)公平鎖雄坪、鎖可以綁定多個條件

  • 等待可中斷:當持有鎖的線程長期不釋放鎖的時候厘熟,正在等待的線程可以選擇放棄等待,改為處理其他事情维哈,可中斷性對處理執(zhí)行時間非常長的同步快很有幫助
  • 公平鎖:是指多個線程等待同一個鎖時绳姨,必須按照申請鎖的時間順序來一次獲得鎖;而非公平鎖無法保證這一點阔挠,在鎖被釋放時飘庄,任何一個等待鎖的線程都有機會獲得鎖。synchronized中鎖鎖就鎖非公平的谒亦,ReentrantLock默認鎖也是非公平的竭宰,但是可以通過布爾值的構(gòu)造函數(shù)要求使用公平鎖
  • 以綁定多個條件:指一個ReentrantLock對象可以同時綁定多個Condition對象,而在synchronized中份招,鎖對象的wait()和notify()或notifyAll()方法可以實現(xiàn)一個隱含的條件切揭,如果要和多余一個條件關(guān)聯(lián)的時候,就不得不額外添加一個鎖锁摔,而ReentrantLock則無需這樣做廓旬,只需要多次調(diào)用newCondition()方法即可

JDK1.6之前ReentrantLock性能比synchronized好,1.6后持平

1.2.2非阻塞同步

  • 互斥同步最主要的問題就是進行線程阻塞和喚醒所帶來的性能問題谐腰,所以也叫阻塞同步孕豹。從處理問題的方式說,互斥同步(阻塞同步)屬于一種悲觀的并發(fā)策略(所以叫叫悲觀鎖么十气?励背?)
  • 悲觀的并發(fā)策略:總是認為主要不去做做正確的同步措施(如:加鎖),那家肯定會出現(xiàn)問題砸西,無論共享數(shù)據(jù)是否真的會出現(xiàn)競爭叶眉,它都要進行加鎖、用戶態(tài)到核心態(tài)轉(zhuǎn)換芹枷、維護鎖計數(shù)器和檢查是否有被阻塞的線程需要被喚醒
  • 隨著硬件指令的發(fā)展衅疙,新的選擇:基于沖突檢測的樂觀并發(fā)策略:先執(zhí)行,如果沒有其他線程爭用共享數(shù)據(jù)鸳慈,那操作就成功了饱溢,如果共享數(shù)據(jù)有爭用,產(chǎn)生了沖突走芋,那就再采取其他的補償措施(最常見的補償措施家是不斷的重試绩郎,知直到成功),這種樂觀的并發(fā)策略的許多實現(xiàn)都不需要把線程掛起翁逞,因此這種同步操作稱為非阻塞同步

1.2.3無同步方案

要保證線程安全嗽上,并不一定就要進行同步,兩者沒有因果關(guān)系熄攘,同步只是保證共享數(shù)據(jù)爭用時的正確性的手段兽愤,如果一個方法本來就不涉及共享數(shù)據(jù),那它自然就無需任何同步措施去保證正確性挪圾,因此會有一些代碼天生就是線程安全的

  • 可重入代碼
  • 線程本地存儲-ThreadLocal
    每個線程的Thread對象中都有一個ThreadLocalMap對象浅萧,這個對象存儲了一組以ThreadLocal.threadLocalHashCode為健,以本地線程變量為值的K-V值對哲思,ThreadLocal對象就是當前線程的ThreadLocalMap訪問入口洼畅,每一個ThreadLocal對象都包含了一個獨一無二的threadLocalHashCode值,使用這個值就可以在線程K-V值中找回對于的本地線程變量

2.鎖優(yōu)化

都是虛擬機開發(fā)團隊優(yōu)化鎖機制棚赔,一堆嗶哩吧啦的帝簇,也不知道咋記錄徘郭。想知道具體的,就去百度或者翻書吧

2.1 自旋鎖與自適應(yīng)自旋

2.2鎖消除

2.3鎖粗化

簡單的說就是一個類里丧肴,一塊代碼加一個鎖残揉,還不如整個類都鎖起來。大致是這個意思

2.4輕量級鎖

2.5偏向鎖

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末芋浮,一起剝皮案震驚了整個濱河市抱环,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌纸巷,老刑警劉巖镇草,帶你破解...
    沈念sama閱讀 212,718評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異瘤旨,居然都是意外死亡梯啤,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評論 3 385
  • 文/潘曉璐 我一進店門存哲,熙熙樓的掌柜王于貴愁眉苦臉地迎上來条辟,“玉大人,你說我怎么就攤上這事宏胯∮鸬眨” “怎么了?”我有些...
    開封第一講書人閱讀 158,207評論 0 348
  • 文/不壞的土叔 我叫張陵肩袍,是天一觀的道長杭棵。 經(jīng)常有香客問我,道長氛赐,這世上最難降的妖魔是什么魂爪? 我笑而不...
    開封第一講書人閱讀 56,755評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮艰管,結(jié)果婚禮上滓侍,老公的妹妹穿的比我還像新娘。我一直安慰自己牲芋,他們只是感情好撩笆,可當我...
    茶點故事閱讀 65,862評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著缸浦,像睡著了一般夕冲。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上裂逐,一...
    開封第一講書人閱讀 50,050評論 1 291
  • 那天歹鱼,我揣著相機與錄音,去河邊找鬼卜高。 笑死弥姻,一個胖子當著我的面吹牛南片,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播庭敦,決...
    沈念sama閱讀 39,136評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼疼进,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了螺捐?” 一聲冷哼從身側(cè)響起颠悬,我...
    開封第一講書人閱讀 37,882評論 0 268
  • 序言:老撾萬榮一對情侶失蹤矮燎,失蹤者是張志新(化名)和其女友劉穎定血,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體诞外,經(jīng)...
    沈念sama閱讀 44,330評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡澜沟,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,651評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了峡谊。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片茫虽。...
    茶點故事閱讀 38,789評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖既们,靈堂內(nèi)的尸體忽然破棺而出濒析,到底是詐尸還是另有隱情,我是刑警寧澤啥纸,帶...
    沈念sama閱讀 34,477評論 4 333
  • 正文 年R本政府宣布号杏,位于F島的核電站,受9級特大地震影響斯棒,放射性物質(zhì)發(fā)生泄漏盾致。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,135評論 3 317
  • 文/蒙蒙 一荣暮、第九天 我趴在偏房一處隱蔽的房頂上張望庭惜。 院中可真熱鬧,春花似錦穗酥、人聲如沸护赊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽百揭。三九已至,卻和暖如春蜓席,著一層夾襖步出監(jiān)牢的瞬間器一,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評論 1 267
  • 我被黑心中介騙來泰國打工厨内, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留祈秕,地道東北人渺贤。 一個月前我還...
    沈念sama閱讀 46,598評論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像请毛,于是被迫代替她去往敵國和親志鞍。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,697評論 2 351

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