線程的基本使用

1.synchronized之錯誤的加鎖和原因分析

  • 鎖一定要加在一個不變的對象上



  • volatile 關鍵字穿稳,最輕量的同步機制
    volatile 保證了不同線程對這個變量進行操作時的可見性叁熔,即一個線程修改了某 個變量的值,這新值對其他線程來說是立即可見的证九。
    可以保證可見彭谁,但是不能保證原子
    volatile 最適用的場景:一個線程寫吸奴,多個線程讀。

2.ThreadLocal辨析

ThreadLocal 為每個線程都提供了變量的副本缠局,使得每個線程在某一時間訪問到的并非同一個對象则奥,這樣就隔離了多個線程對數(shù)據的數(shù)據共享

  • void set(Object value) 設置當前線程的線程局部變量的值。
  • public Object get() 該方法返回當前線程所對應的線程局部變量狭园。
  • public void remove() 將當前線程局部變量的值刪除读处,目的是為了減少內存的占用。
  • protected Object initialValue()返回該線程局部變量的初始值唱矛,該方法是一個 protected 的方法罚舱,顯然是為 了讓子類覆蓋而設計的。
ThreadLocal辨析

每個線程獨有的 ThreadLocalMap 然后再用 ThreadLocal 的當前實例绎谦,拿到 Map 中的相應的 Entry管闷,然后就可 以拿到相應的值返回出去。當然窃肠,如果 Map 為空包个,還會先進行map 的創(chuàng)建,初始化等工作冤留。

  • ThreadLocal可能會產生內存泄漏


    圖中的虛線表示弱引用赃蛛。
    這樣恃锉,當把 threadlocal 變量置為 null 以后,沒有任何強引用指向 threadlocal 實例呕臂,所以 threadlocal 將會被 gc 回收。這樣一來肪跋,ThreadLocalMap 中就會出現(xiàn) key 為 null 的 Entry歧蒋,就沒有辦法訪問這些 key 為 null 的 Entry 的 value,如果當前 線程再遲遲不結束的話州既,這些 key 為 null 的 Entry 的 value 就會一直存在一條強 引用鏈:Thread Ref -> Thread -> ThreaLocalMap -> Entry -> value谜洽,而這塊 value 永 遠不會被訪問到了,所以存在著內存泄露吴叶。

ThreadLocal 內存泄漏的根源是:由于 ThreadLocalMap 的生命周期跟 Thread 一樣長阐虚,如果沒有手動刪除對應 key 就會導致內存泄漏,而不是因為弱引 用蚌卤∈凳總結 JVM 利用設置 ThreadLocalMap 的 Key 為弱引用,來避免內存泄露逊彭。 JVM 利用調用 remove咸灿、get、set 方法的時候侮叮,回收弱引用避矢。 當 ThreadLocal 存儲很多 Key 為 null 的 Entry 的時候,而不再去調用 remove囊榜、 get审胸、set 方法,那么將導致內存泄漏卸勺。 使用線程池+ ThreadLocal 時要小心砂沛,因為這種情況下,線程是一直在不斷的 重復運行的孔庭,從而也就造成了 value 可能造成累積的情況尺上。

  • ThreadLocal線程不安全的情況
    每個線程中的 ThreadLocal 都應該持有一個新的 Number 對象。

3.線程之間的協(xié)作

  • 等待和通知
    wait():調用該方法的線程進入 WAITING 狀態(tài),只有等待另外線程的通知或被中斷 才會返回.需要注意,調用 wait()方法后,會釋放對象的鎖
    notify/notifyAll
    通知一個在對象上等待的線程,使其從 wait 方法返回,而返回的前提是該線程 獲取到了對象的鎖圆到,沒有獲得鎖的線程重新進入 WAITING 狀態(tài)怎抛。

  • 等待和通知的標準范式
    等待方遵循如下原則。
    1)獲取對象的鎖芽淡。
    2)如果條件不滿足马绝,那么調用對象的 wait()方法,被通知后仍要檢查條件挣菲。
    3)條件滿足則執(zhí)行對應的邏輯富稻。



    通知方遵循如下原則掷邦。
    1)獲得對象的鎖。
    2)改變條件椭赋。
    3)通知所有等待在對象上的線程抚岗。


  • notify 和 notifyAll 應該用誰 盡可能用 notifyall(),謹慎使用 notify()哪怔,因為 notify()只會喚醒一個線程宣蔚,我 們無法確保被喚醒的這個線程一定就是我們需要喚醒的線程

  • 調用 yield() 、sleep()认境、wait()胚委、notify()等方法對鎖有何影響?
    yield() 叉信、sleep()被調用后亩冬,都不會釋放當前線程所持有的鎖。 調用 wait()方法后硼身,會釋放當前線程持有的鎖硅急,而且當前被喚醒后,會重新 去競爭鎖鸠姨,鎖競爭到后才會執(zhí)行 wait 方法后面的代碼铜秆。 調用 notify()系列方法后,對鎖無影響讶迁,線程只有在 syn 同步代碼執(zhí)行完后才 會自然而然的釋放鎖连茧,所以 notify()系列方法一般都是 syn 同步代碼的最后一行。

4.線程的并發(fā)工具類

  • Fork-Join(分而治之的算法)


    Fork-Join原理
  • 工作密取
    當前線程的 Task 已經全被執(zhí)行完畢巍糯,則自動取到其他線程的 Task 池中取 出 Task 繼續(xù)執(zhí)行啸驯。


    工作密取
  • Fork/Join 使用的標準范式


    Fork/Join 使用的標準范式
  • CountDownLatch(閉鎖)
    閉鎖,CountDownLatch 這個類能夠使一個線程等待其他線程完成各自的工 作后再執(zhí)行祟峦。例如罚斗,應用程序的主線程希望在負責啟動框架服務的線程已經啟動 所有的框架服務之后再執(zhí)行。
    CountDownLatch 是通過一個計數(shù)器來實現(xiàn)的宅楞,計數(shù)器的初始值為初始任務 的數(shù)量针姿。每當完成了一個任務后,計數(shù)器的值就會減 1 (CountDownLatch.countDown()方法)厌衙。當計數(shù)器值到達 0 時距淫,它表示所有的已 經完成了任務,然后在閉鎖上等待 CountDownLatch.await()方法的線程就可以恢 復執(zhí)行任務婶希。

  • CyclicBarrier
    會讓所有線程都等待完成后才會繼續(xù)下一步行動

  • Semaphore
    Semaphore 通常我們叫它信號量榕暇, 可以用來控制同時訪問特定資源的線程數(shù)量,通過協(xié)調各個線程,以保證合理的使用資源彤枢。

  • Exchange
    Exchange位于java.util.concurrent包下面狰晚,主要是用于線程之間數(shù)據交換的工具類,經常用于管道設計和遺傳算法中

6.線程的狀態(tài)

  • 初始(new)
  • 運行中(running)
  • 就緒(ready)
  • 等待(waiting)
  • 等待超時(timed_waiting)
  • 終止(terminated)
  • 阻塞(blocked)
線程的狀態(tài)
  • 死鎖
    死鎖是指兩個或兩個以上的進程在執(zhí)行過程中缴啡,由于競爭資源或者由于彼此通信而造成的一種阻塞的現(xiàn)象壁晒,若無外力作用,它們都將無法推進下去盟猖。此時稱系統(tǒng)處于死鎖狀態(tài)或系統(tǒng)產生了死鎖讨衣。

產生條件:
1.多個操作者爭奪多個資源
2.爭奪資源的順序不對
3.拿到資源不放手
學術說法:
1.互斥條件
2.請求和保持
3.不剝奪
4.環(huán)路等待

  • 活鎖
    兩個線程在嘗試拿鎖的機制中,發(fā)生多個線程之間互相謙讓式镐,不斷發(fā)生同一個線程總是拿到同一把鎖,在嘗試拿另一把鎖時因為拿不到固蚤,而將本來已經持有的鎖釋放的過程娘汞。
    解決辦法:每個線程休眠隨機數(shù),錯開拿鎖的時間夕玩。

  • 線程饑餓
    低優(yōu)先級的線程你弦,總是拿不到執(zhí)行時間

7.CAS(Compare And Swap)

  • 什么是原子操作?如何實現(xiàn)原子操作燎孟?
    假定有兩個操作A和B(A和B可能都很復雜)禽作,如果從執(zhí)行A的線程來看,當另一個線程執(zhí)行B時揩页,要么將B全部執(zhí)行完旷偿,要么完全不執(zhí)行B,那么A和B對彼此來說是原子的爆侣。
    synchronized關鍵字是基于阻塞的鎖機制萍程,也就是說當一個線程擁有鎖的時候,訪問同一資源的其它線程需要等待兔仰,直到該線程釋放鎖

  • CAS原理
    基本思路就是茫负,如果這個地址上的值和期望的值相等,則給其賦予新值乎赴,否則不做任何事兒忍法,但是要返回原值是多少。循環(huán)CAS就是在一個循環(huán)里不斷的做cas操作榕吼,直到成功為止饿序。

synchronized  悲觀鎖 
CAS 樂觀鎖
  • CAS的問題
    1.ABA問題
    因為CAS需要在操作值的時候,檢查值有沒有發(fā)生變化友题,如果沒有發(fā)生變化則更新嗤堰,但是如果一個值原來是A,變成了B,又變成了A踢匣,那么使用CAS進行檢查時會發(fā)現(xiàn)它的值沒有發(fā)生變化告匠,但是實際上卻變化了。
    ABA問題的解決思路就是使用版本號离唬。在變量前面追加上版本號后专,每次變量更新的時候把版本號加1,那么A→B→A就會變成1A→2B→3A输莺。
    2.循環(huán)時間長開銷大戚哎。
    自旋CAS如果長時間不成功,會給CPU帶來非常大的執(zhí)行開銷嫂用。
    3.只能保證一個共享變量的原子操作型凳。

  • Jdk中相關原子操作類的使用
    更新基本類型類:AtomicBoolean,AtomicInteger嘱函,AtomicLong
    更新數(shù)組類:AtomicIntegerArray甘畅,AtomicLongArray,AtomicReferenceArray
    更新引用類型:AtomicReference往弓,AtomicMarkableReference疏唾,AtomicStampedReference

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市函似,隨后出現(xiàn)的幾起案子槐脏,更是在濱河造成了極大的恐慌,老刑警劉巖撇寞,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件顿天,死亡現(xiàn)場離奇詭異,居然都是意外死亡重抖,警方通過查閱死者的電腦和手機露氮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來钟沛,“玉大人畔规,你說我怎么就攤上這事『尥常” “怎么了叁扫?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長畜埋。 經常有香客問我莫绣,道長,這世上最難降的妖魔是什么悠鞍? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任对室,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘掩宜。我一直安慰自己蔫骂,他們只是感情好,可當我...
    茶點故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布牺汤。 她就那樣靜靜地躺著辽旋,像睡著了一般。 火紅的嫁衣襯著肌膚如雪檐迟。 梳的紋絲不亂的頭發(fā)上补胚,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天,我揣著相機與錄音追迟,去河邊找鬼溶其。 笑死,一個胖子當著我的面吹牛敦间,可吹牛的內容都是我干的握联。 我是一名探鬼主播,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼每瞒,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了纯露?” 一聲冷哼從身側響起剿骨,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎埠褪,沒想到半個月后浓利,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡钞速,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年贷掖,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片渴语。...
    茶點故事閱讀 38,622評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡苹威,死狀恐怖,靈堂內的尸體忽然破棺而出驾凶,到底是詐尸還是另有隱情牙甫,我是刑警寧澤,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布调违,位于F島的核電站窟哺,受9級特大地震影響,放射性物質發(fā)生泄漏技肩。R本人自食惡果不足惜且轨,卻給世界環(huán)境...
    茶點故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧旋奢,春花似錦泳挥、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至爽丹,卻和暖如春筑煮,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背粤蝎。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工真仲, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人初澎。 一個月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓秸应,卻偏偏與公主長得像,于是被迫代替她去往敵國和親碑宴。 傳聞我的和親對象是個殘疾皇子软啼,可洞房花燭夜當晚...
    茶點故事閱讀 43,490評論 2 348

推薦閱讀更多精彩內容