多線程、鎖相關知識

多線程、鎖

線程池

  • 線程池的好處
    1.資源利用率變高了
    2.提高了響應速度
    3.利於管理線程
  • 實現原理(線程複用、管理線程):
    線程複用原理:
    線程複用原理
    解釋:線程池中有幾個工作類:本身是一個runnable,內部還有一個線程,啓動線程也就是啓動了本身;
    worker的任務就是不斷從隊列裏面拉去任務,然後執行任務的run方法,也就是說每一個worker就是串行執行任務。
    管理線程實現原理:
    在ThreadPoolExecutor有個ctl的AtomicInteger變量。通過這一個變量保存了兩個內容:
    1.所有線程的數量
    2.每個線程所處的狀態
    其中低29位存線程數,高3位存runState,通過位運算來得到不同的值。
  • 拒絕策略
    1.CallerRunsPolicy:線程調用運行該任務的 execute 本身
    2.AbortPolicy:處理程序遭到拒絕將拋出運行時 RejectedExecutionException
    3.DiscardPolicy:不能執行的任務將被刪除,不報錯
    4.DiscardOldestPolicy:工作隊列頭部的任務將被刪除,然後重試加入此任務。

競態條件(race condition):

是指設備或系統出現不恰當的執行時序,而得到不正確的結果。

檢測一個線程是否擁有鎖

在java.lang.Thread中有一個方法叫holdsLock(obj),它返回true如果當且僅當當前線程擁有某個具體對象的鎖。

鎖分類

  • 悲觀鎖/樂觀鎖
    悲觀鎖:認爲操作會有競爭,那麼不管有沒有,爲了保險,直接加鎖
    樂觀鎖:認爲操作很少有競爭,那麼就不加鎖,大多用cas實現,如果失敗就重試
  • 公平鎖/非公平鎖
    公平鎖:公平鎖則在於每次都是按照先後順序來分配
    非公平鎖:隨機分配鎖資源給一個等待線程
  • 獨享鎖/共享鎖
    獨享鎖:單個線程獨佔
    共享鎖:允許多個線程持有
  • 自旋鎖/自適應自旋鎖
    自旋鎖:線程空等待,知道獲得鎖資源
    自適應自旋鎖:自適應意味着自旋的時間不再固定了,而是由前一次在同一個鎖上的自旋時間及鎖的擁有者的狀態來決定:如果在同一個鎖對象上,自旋等待剛剛成功獲得過鎖,並且持有鎖的線程正在運行中,那麼虛擬機就會認爲這次自旋也很有可能再次成功,進而它將允許自旋等待持續相對更長的時間,比如100個循環。
    相反的,如果對於某個鎖,自旋很少成功獲得過,那在以後要獲取這個鎖時將可能減少自旋時間甚至省略自旋過程,以避免浪費處理器資源。
  • 偏向鎖/輕量級鎖/重量級鎖
    實現過程:對象頭數據含有mark word數據,有一個鎖標誌位(00輕量級、01偏向、10重量級)和可變數據結構
    輕量級鎖:線程棧中建立一個mark word的副本,通過cas操作將鎖的mark word複製過來,對象頭的指針指向這個棧指針,標誌位爲00,
    執行同步操作,釋放鎖就cas替換回去,如果失敗,表示鎖升級爲10重量級鎖。
    偏向鎖:當鎖對象第一次被線程請求的時候,mark word記錄當前的線程id,如果以後還來,直接進,如果另外的線程請求,那麼升級成輕量級鎖。
    重量級鎖:先獲取鎖,操作,最後釋放鎖

volatile關鍵字

  • 所標記的變量爲唯一內容,每個工作內存要用到這個變量的時候,是最新的主內存變量,也就是說,這個變量的狀態對所有線程都是透明的,
    如果需要對該變量寫操作,那麼立即刷新會主內存。
  • 禁止指令重排序,內存屏障的機制

synchronized關鍵字和Lock的使用區別

  • synchronized不支持超時放棄
  • synchronized是不公平鎖
  • synchronized是原生java底層實現,而lock是一個併發類

synchronized的鎖

重量級鎖:對應於操作系統的mutex互斥鎖

  • 對象頭信息中有關標誌位
  • 鎖升級過程
    • 偏向鎖01 => 輕量級鎖00
    • 輕量級鎖00 => 重量級鎖10

AQS的實現原理

內部有一個volatile的state變量和一個雙向鏈表(存線程隊列)
上鎖過程:嘗試請求,如果成功,那麼執行,如果失敗,加入隊尾,如果是老二,那麼自旋cas請求資源,
否則依次往前找到一個確實等待的線程,接在後面,之間的失效節點都丟了。
釋放鎖過程:cas歸還資源,喚醒下一個有效的等待線程,設置爲head
AQS

獨佔鎖(ReentrantLock)的實現原理

和上述是一樣的

讀寫鎖(ReentrantReadWriteLock)的實現原理

讀鎖、寫鎖共用一個同步器:低位存寫鎖,高位存讀鎖;
關鍵是存儲讀寫鎖的數量、和讀寫鎖重入的次數

LinkedBlockingDeque實現原理

內部有一個雙向隊列,一個全局鎖和兩個信號(空,滿)
當獲取時如果沒有,喚醒被滿信號量阻塞的生產者,自己阻塞
當添加的時候滿了,喚醒被空信號量阻塞的消費者,自己阻塞

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章