1. 程式人生 > 實用技巧 >spring boot: 用redis的訊息訂閱功能更新應用內的caffeine本地快取(spring boot 2.3.2)

spring boot: 用redis的訊息訂閱功能更新應用內的caffeine本地快取(spring boot 2.3.2)

1 公平鎖/非公平鎖

公平鎖:多個執行緒申請獲取同一個鎖,按照執行緒的申請順序,排隊獲取鎖。公平鎖的好處是等待的執行緒不會被餓死,相應的缺陷 就是整體吞吐量很低、效率很低,使用new ReentrantLock(true)可以構造一個公平鎖。

非公平鎖:多個執行緒申請獲取同一個鎖,獲取鎖的順序不按照申請順序,搶佔式的獲取。非公平鎖的好處是整體效率很高,但是 可能會使有些執行緒一致在等待,造成餓死。使用Synchronized、new ReentrantLock()和new ReentrantLock(false)可 以構建一 個非公平鎖。

2 可重入鎖

可重入鎖:也稱為遞迴鎖,即執行緒在獲取到某方法的鎖之後,如果在該方法內部呼叫其它方法,這個方法也需要獲取鎖,那麼 進入這個方法將自動獲取鎖,它可以在一定程度上避免死鎖。

3 獨享鎖/共享鎖

共享鎖:簡單的理解就是鎖可以被多個執行緒持有。在實際使用過程中,執行緒A獲取到了共享資源D的共享鎖,其它執行緒只能獲取 D的共享鎖,不能獲取獨佔鎖。

獨佔鎖:一次只能有一個執行緒獲得鎖,即只能被一個執行緒持有。在實際使用過程中,執行緒A獲取到了共享資源D的獨佔鎖,其它 執行緒不能獲取D的任何型別鎖。

4 互斥鎖/讀寫鎖

互斥鎖:即一次只能有一個執行緒持有的鎖。ReentrantLock和synchronized都是互斥鎖。

讀寫鎖:一次只有一個執行緒(writer執行緒)可以修改共享資料,但在許多情況下,任何數量的執行緒可以同時讀取共享資料 (reader執行緒)。Java中的讀寫鎖通過ReentrantReadWriteLock實現。ReentrantReadWriteLock.ReadLock是讀鎖,它 是共享鎖。ReentrantReadWriteLock.WriteLock是寫鎖,它是獨佔鎖。

5 樂觀鎖/悲觀鎖

悲觀鎖:認為對同一資料的併發操作一定會出現衝突問題,所以,在對資料操作之前一定要加鎖。Java編碼中悲觀鎖的實現有很 多種,for update就是一種。

樂觀鎖:認為對同一資料的併發操作不會出現衝突問題,資料操作不加鎖,會在操作提交時檢查資料的完整性。Java中常用的樂 觀鎖方式有版本號、時間戳

6 分段鎖

分段鎖其實是一種鎖的設計,並不是具體的一種鎖,對於ConcurrentHashMap而言,其併發的實現就是通過分段鎖的形式來實現高效的併發操作。我們以ConcurrentHashMap來說一下分段鎖的含義以及設計思想,ConcurrentHashMap中的分段鎖稱為 Segment,它即類似於 HashMap(JDK7 與 JDK8 中 HashMap 的實現)的結構,即內部擁有一個 Entry 陣列,陣列中的每個元素既是一個連結串列;同時又是一個 ReentrantLock(Segment 繼承了 ReentrantLock)。當需要 put 元素的時候,並不是對整個 hashmap 進行加鎖,而是先通過 hashcode 來知道他要放在那一個分段中,然後對這個分段進行加鎖,所以當多執行緒 put 的時候,只要不是放在一個分段中,就實現了真正的並行的插入。但是,在統計 size 的時候,可就是獲取 hashmap 全域性資訊的時候,就需要獲取所有的分段鎖才能統計。分段鎖的設計目的是細化鎖的粒度,當操作不需要更新整個陣列的時候,就僅僅針對陣列中的一項進行加鎖操作。

7 偏向鎖/輕量級鎖/重量級鎖

這三個鎖都是針對synchronized來說的,具體的實現細節比較複雜,這裡不展開細說。

偏向鎖:對於一段同步程式碼來說,鎖偏向於第一次獲取它的執行緒,如果繼續執行的過程中,鎖沒有被其它執行緒持有,則持有偏向鎖的執行緒將不需要同步,自動獲取鎖。

輕量級鎖:當偏向鎖被另一個執行緒持有的時候,偏向鎖升級為輕量級鎖,其它執行緒通過自旋轉的方式嘗試獲取鎖。

重量級鎖:當輕量級鎖被另一個執行緒持有的時候,輕量級鎖升級為重量級鎖。

優點 缺點 適用場景
偏向鎖 加鎖和解鎖不需要額外的消耗,和執行非同步方法相比僅存在納秒級的差距 如果執行緒間存在鎖競爭,會帶來額外的所撤銷的消耗 適用於只有一個執行緒訪問同步塊場景
輕量級鎖 競爭的執行緒不會阻塞,提高了程式的響應速度 如果始終得不到鎖競爭的執行緒,使用自旋會消耗CPU 追求相應速度,同步塊執行速度非常塊
重量級鎖 執行緒競爭不適用自旋,不會消耗CPU 執行緒阻塞,相應時間緩慢 追求吞吐量,同步塊執行速度較長

8 自旋鎖

Java執行緒在得不到鎖時不會立即阻塞,而是執行一個迴圈,不斷的去嘗試獲取鎖,這種技術就是自旋鎖。它可以減少在獲取鎖的過程中,因為執行緒上下文的切換而導致的額外消耗。

9 可重入鎖

可重入鎖:也稱為遞迴鎖,即執行緒在獲取到某方法的鎖之後,如果在該方法內部呼叫其它方法,這個方法也需要獲取鎖,那麼進入這個方法將自動獲取鎖,它可以在一定程度上避免死鎖。