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

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)

    分享創造快樂