歡迎光臨
每天分享高質量文章

Java併發程式設計:概念和原理

音樂資源載入中…

關鍵概念

背景關係切換

  1. 概念:CPU透過時間片演演算法,給可執行的執行緒分配執行時間,在不同執行緒之間的切換時需要將當前執行緒的狀態儲存並回覆將要執行的執行緒狀態資訊,這個過程就是背景關係切換。

  2. 如何減少或避免背景關係切換?

  • 無鎖併發程式設計

  • CAS演演算法

  • 使用最少執行緒

  • 協程

死鎖

  1. 概念:兩個或多個執行緒持有對方正在等待的鎖

  2. 如何避免死鎖?

  • 避免一個執行緒同時獲取多個鎖

  • 避免一個執行緒在鎖內同時佔用多個資源,儘量保證每個鎖只佔用一個資源

  • 嘗試使用定時鎖

  • 對於資料庫鎖,加鎖和解鎖必須在一個資料庫連線裡

Java併發的底層機制

volatile

  1. 作用:在多處理器開發中保證多執行緒之間的共享變數的可見性,即一個執行緒修改該變數的值時,其他的執行緒可以立即看到該變數最新的值。

  2. 原理:對被volatile修飾的變數進行寫操作時,會做如下兩個事情

  • 將當前處理器快取行的資料寫到系統記憶體;

  • 使得其他CPU裡快取了該記憶體地址的資料無效

  • 使用要點:

    • volatile只能保證可見性,無法保證同步性。舉個例子:如果針對某個變數的改變後的值依賴於上次改變的值,使用volatile就無法保證併發安全了

    synchronized

    1. 定義:synchronized是Java多執行緒之間的一種通訊方式。synchronized的具體應用有三種:

    • 對於普通同步方法,鎖是當前實體物件

    • 對於靜態同步方法,鎖是當前類的Class物件

    • 對於同步程式碼塊,鎖是synchronized括號裡配置的物件

  • 使用要點:

    • 構造方法不能用synchronized修飾

    • 推薦儘量減小鎖的粒度,例如,使用同步程式碼塊可以滿足需求就不需要使用同步方法

    • 如果可以確認應用中的所有鎖在大多數情況下都由不同的執行緒競爭,可以透過-XX:+UseBiasedLocking禁用偏向鎖,提升效能。

  • 原理:介紹兩個概念,Monitor Record(Thread類的私有資料結構)和Java物件頭,關係是:Java物件頭中儲存了Monitor Record的地址,Monitor Record中記錄了持有它的執行緒。

    • monitor:monitor不是一個特殊的物件,是一種方法或機制,Java透過monitor來控制對某個物件的訪問。Java中的每個物件都和一個monitor相關聯。在同一個時刻,只有一個執行緒(Thread)可以鎖定一個monitor。當某個monitor被一個執行緒鎖定時,其他試圖鎖定這個monitor的執行緒只能block等待。

    • 物件頭:synchronized的鎖狀態描述在Java物件的頭部。物件頭中包括Mark word和Klass Word。在32位虛擬機器中,整個物件頭大小是64bits(即8位元組),Mark Word和Klass Word分別佔用4位元組。

    1. 鎖狀態:Java中的鎖按照級別從低到高有四種,無鎖狀態——>偏向鎖——>輕量級鎖——>重量級鎖。偏向鎖是依賴Mark Word中的一個指向當前執行緒的欄位來標識該鎖的持有者是否是當前執行緒,如果是則直接進入同步程式碼塊;假設禁用了偏向鎖,輕量級鎖指的是兩個執行緒獲取鎖,一個獲取到,另一個獲取不成功的狀態,首先會CAS自旋獲取鎖,如果CAS自旋獲取失敗,該輕量級鎖就會膨脹為重量級鎖,當前獲取鎖失敗的執行緒進入阻塞狀態。

    2. 鎖升級的過程,只會從低到高,不會從高到低,避免不必要的資源浪費。舉個例子,如果一個鎖的狀態已經達到重量級鎖,後面再來競爭這個鎖的執行緒都會直接進入阻塞,不會再進行CAS自旋。參考資料7中提供的一張圖很精緻,我放在這裡:

    原子操作

    CPU級別的原子操作

    在CPU級別實現原子操作需要依靠CPU指令完成,CPU指令透過匯流排操作記憶體中的資料,因此在CPU中有兩個方式:

    1. 鎖匯流排:利用LOCK指令向匯流排發出訊號,實現一個

    2. 鎖快取:在某個一時刻,只需要保證對某個記憶體地址的操作是原子性的;

    JAVA中的原子操作

    在Java中可以透過CAS和鎖來實現原子操作。

    1. 使用CAS實現原子操作,從Java1.5開始,java.lang.concurrent包裡提供了很多類來支援原子操作,例如AotmicIntengerAtomicLong,這些類可以以原子的方式將變數的當前值加1或減1;

    2. 使用鎖實現原子操作,鎖機制確保只有持有鎖的執行緒才能操作指定的變數;

    參考資料

    1. Java併發程式設計的藝術

    2. 深入理解Java記憶體模型系列l

    3. 多執行緒知識梳理(3) – synchronized 三部曲之鎖最佳化

    4. The Java Tutorails

    5. Java併發程式設計:Synchronized底層最佳化(偏向鎖、輕量級鎖)

    6. What’s a monitor in Java?

    7. 官方檔案:Threads and Locks

    8. 力薦:Object Header示例

    9. Java Synchronized機制

    10. OpenJDK檔案:Synchronization

    贊(0)

    分享創造快樂