【Java 并发编程】线程锁机制 ( 锁的四种状态 | 无锁状态 | 偏向锁 | 轻量级锁 | 重量级锁 | 锁竞争 | 锁升级 )
文章目錄
- 一、悲觀鎖示例 ( ReentrantLock )
- 二、重量級鎖弊端
- 三、鎖的四種狀態 ( 無鎖狀態 | 偏向鎖 | 輕量級鎖 | 重量級鎖 )
- 四、鎖的四種狀態之間的轉換 ( 無鎖狀態 -> 偏向鎖 -> 輕量級鎖 -> 重量級鎖 )
一、悲觀鎖示例 ( ReentrantLock )
ReentrantLock 與 synchronized 都是悲觀鎖 ;
ReentrantLock 是 Lock 接口的實現類 ,
public class ReentrantLock implements Lock, java.io.Serializable { }Lock 是一種鎖的機制 , 調用 lock() 方法 , 表示要對下方的代碼進行加鎖 , 這些代碼是線程安全的 ;
代碼執行完畢后 , 調用 unlock() 釋放鎖 ;
在 lock() 與 unlock() 之間的內容 , 就是同步代碼塊內容 ;
public interface Lock {void lock();void lockInterruptibly() throws InterruptedException;boolean tryLock();boolean tryLock(long time, TimeUnit unit) throws InterruptedException;void unlock();Condition newCondition(); }悲觀鎖都是重量級鎖 ;
二、重量級鎖弊端
JDK 1.21.21.2 之間 , 只有一個 synchronized 重量級鎖 ;
Java 虛擬機創建了線程 A , B 兩個線程 , JVM 將線程托管給操作系統進行調度執行 , 線程同步依靠 synchronized 重量級鎖實現 , 線程 A , B 之間會進行競爭 , 哪個搶到 synchronized 鎖 , 哪個線程就可以執行 ;
使用 synchronized 使用起來效率很低 , 假如在 synchronized 同步代碼塊中 , 只有一行代碼 , 執行 111 ms , 但是系統調度線程 , 可能需要 202020 ms 才能輪到線程執行 , 線程執行的時間遠遠小于調度時間 , 這樣線程執行效率很低 ;
為了 Java 程序的提升執行效率 , Java 引入了 444 種鎖狀態 , 無鎖 , 偏向鎖 , 輕量級鎖 , 重量級鎖 ;
三、鎖的四種狀態 ( 無鎖狀態 | 偏向鎖 | 輕量級鎖 | 重量級鎖 )
Java 虛擬機堆內存中的對象數據中 , 每個對象都有一個對象頭 , 結構如下 :
對象頭 中封裝了 鎖的狀態 , 當鎖的狀態發生改變時 , 對應的鎖的標志位也進行相應修改 ;
無鎖狀態 : 不進行加鎖 , 線程不安全 ;
偏向鎖 : 第 111 個訪問 共享資源 的線程 A , 做一個標記 , 不加鎖 , 這個標記稱為 " 偏向鎖 " ; 偏向鎖 偏向第一個訪問的線程 ; 如果沒有新的線程競爭該鎖 , 則該 偏向鎖一直被該線程持有 , 不會釋放鎖 ; 如果出現多個線程同時訪問 , 持有偏向鎖的線程會 釋放該偏向鎖 , 并添加輕量級鎖 ;
- 鎖競爭 : 多個線程嘗試獲取同一個鎖 ;
- 沒有競爭 : 如果每次獲取都很順利 , 沒有出現阻塞 , 則沒有競爭 ;
- 有競爭 : 如果線程嘗試獲取鎖 , 但是鎖被其它線程持有 , 那么 該線程需要等待 , 期間 阻塞或自旋 , 只要是等待就會產生消耗 , 這就產生了鎖競爭 , 并且 有一定的性能消耗 ;
- 鎖競爭消耗 : 多數情況下鎖會被多個線程獲取多次 , 多個線程競爭一個鎖 , 這樣就存在競爭 , 競爭期間 阻塞或自旋 , 鎖獲取的代價很大 ;
- 偏向鎖優點 : 降低了線程獲取鎖的代價 , 偏向鎖不存在鎖競爭問題 ;
- 偏向鎖意義 : 偏向鎖并 不是真正意義上的鎖 , 只是給單線程執行加了層保險 , 如果沒有線程競爭該鎖 , 則正常執行 , 如果有線程競爭 , 則將偏向鎖升級為輕量級鎖 ;
輕量級鎖 : 自旋鎖 , 等待期間一直做自旋操作 , 效率較高 , 但是空耗 CPU 性能 ; 自旋就是 while / for 循環 ;
重量級鎖 : 系統提供的 synchronized , ReentrantLock 等重量級鎖 , 由操作系統進行調度 , 可進行阻塞 ;
四、鎖的四種狀態之間的轉換 ( 無鎖狀態 -> 偏向鎖 -> 輕量級鎖 -> 重量級鎖 )
鎖的四種狀態之間轉換 : 在保證線程安全的前提下 , 盡可能提升效率 ;
-
無鎖 : 剛開始執行時 , 無鎖 ;
-
無鎖 -> 偏向鎖 : 第 111 個線程訪問共享資源時 , 無鎖狀態升級為偏向鎖 ;
-
偏向鎖 -> 輕量級鎖 : 第 222 個線程再來訪問 共享資源 時 , 偏向鎖 升級為 輕量級鎖 ;
-
輕量級鎖 -> 重量級鎖 : 如果 自旋線程數 超過 CPU 核數一半 , 或 單個線程超過 101010 次自旋 , 自動將鎖升級為重量級鎖 ;
總結
以上是生活随笔為你收集整理的【Java 并发编程】线程锁机制 ( 锁的四种状态 | 无锁状态 | 偏向锁 | 轻量级锁 | 重量级锁 | 锁竞争 | 锁升级 )的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Java 并发编程】线程锁机制 ( 悲
- 下一篇: 【错误记录】SeeMusic 一直卡在主