【多執行緒總結(二)-執行緒安全與執行緒同步】

我是太陽啦啦啦發表於2018-09-09

前言:

繼前一篇部落格,今天我們們這篇部落格來說說執行緒安全與執行緒同步那些事.

核心:

初識 synchronized關鍵字
  可以實現一個簡單的策略防止執行緒干擾和記憶體一致性錯誤,如果一個物件對多個執行緒是可見的那麼對該物件的所有讀或者寫都將通過同步的方式來進行.
   提供了一種鎖的機制,能夠確保共享變數的互斥訪問,從而防止資料不一致問題的出現.
 包含兩個jvm命令,monitor enter和monitor exit兩個JVM指令,它能夠保證在任何時候任何執行緒執行到monitor enter成功之前都必須從主記憶體中獲取資料,而不是從快取中,在monitor exti執行成功之後,共享變數被更新後的值必須刷入主記憶體.
  嚴格遵守java happens -before規則,一個monitor exti指令之前必定要有一個monitor enter.
synchronized關鍵字的用法:
  可以對程式碼塊或方法進行修飾,不能夠用於對class以及變數進行修飾.
 1.同步方法:

[default|public|private|protected] synchronized [static] type

 2.同步程式碼塊

Private final Object NUTEX = NEW Object();
Public void sync()
{
    Synchronized(MUTEX)
    {
        …
        …
}
}

深入synchronized關鍵字
  使用synchronized需要注意的問題
   1.與monitor關聯的物件不能為空
   2.synchronized作用域太大
     由於synchronized關鍵字存在排他性,也就是說所有的執行緒必須序列的經過synchronized保護的共享區域,如果synchronized作用域越大,則代表著其效率越低,設定還會喪失併發的優勢
   synchronized關鍵字應該儘可能的只作用於共享資源的讀寫作用域
  3.不同的monitor企圖鎖相同的方法
  4.多個鎖的交叉導致死鎖
this monitor和class monitor的詳細介紹
  程式死鎖的原因以及如何診斷
  程式死鎖類似於交通堵塞現象
  程式死鎖:
   交叉鎖可導致程式出現死鎖:執行緒A持有R1的鎖等待R2的鎖,執行緒B持有R2的鎖等待獲取R1的鎖
   記憶體不足:
當併發請求系統可用記憶體,如果此時系統記憶體不足,則可能會出現死鎖的情況.
  一問一答式的資料交換
服務端開啟某個埠,等待客戶端訪問,客戶端傳送請求立即等待接收,由於某種原因服務端錯誤了客戶端的請求,仍然在等待一問一答的資料交換
  資料庫鎖
無論是資料庫表級別的鎖哈市行級別的鎖,比如某個執行緒執行for update語句退出了事務,其他執行緒訪問資料庫時都將陷入死鎖
   檔案鎖
某執行緒獲得了檔案鎖意外退出,其他讀取檔案的執行緒也將會進入死鎖知道系統釋放檔案控制程式碼資源
死迴圈引起的死鎖
  程式由於程式碼原因或者對某些異常處理不得當,進入了死迴圈,雖然檢視執行緒堆疊資訊不會發現任何死鎖的跡象,但是程式不工作,CPU佔有率又居高不下,這種死鎖一般稱為系統假死,是一種最為致命也是最難排查的死鎖現象
HashMap不具備執行緒安全的能力,如果想要使用執行緒安全的map結構請使用concurentHashMap或者使用Collections.synchronizedMap來替代.
 死鎖診斷:
交叉鎖引起的死鎖,進入blocked狀態,cpu資源佔用不高,很容易藉助工具來發現.開啟jstack工具或者jconsole工具
死迴圈引起的死鎖(假死):處於runnable狀態,CPU使用率居高不下,甚至都不能夠正常執行你的命令.

總結:

相關文章