一文詳細(xì)講解Java中有哪些鎖
1. synchronized 鎖
作用:synchronized
是 Java 最基礎(chǔ)的鎖機(jī)制,用于實現(xiàn)方法或代碼塊的同步,保證多線程環(huán)境下的原子性、可見性和有序性。
使用方式:
對象鎖:修飾實例方法或代碼塊(鎖對象為當(dāng)前實例
this
)。public synchronized void method() { ... } // 實例方法鎖 public void method() { synchronized (this) { ... } // 代碼塊鎖(對象鎖) }
類鎖:修飾靜態(tài)方法或代碼塊(鎖對象為類的
Class
對象)。public static synchronized void staticMethod() { ... } // 靜態(tài)方法鎖 public void method() { synchronized (MyClass.class) { ... } // 代碼塊鎖(類鎖) }
特點:
隱式鎖:自動獲取和釋放鎖,無需手動管理。
可重入:線程可重復(fù)獲取同一把鎖。
非公平鎖:默認(rèn)搶占式獲取鎖,不保證等待時間長的線程優(yōu)先獲取。
適用場景:
簡單同步需求,如單例模式的雙重檢查鎖。
2. ReentrantLock(可重入鎖)
作用:ReentrantLock
是 java.util.concurrent.locks
包下的顯式鎖,提供比 synchronized
更靈活的鎖控制。
使用方式:
ReentrantLock lock = new ReentrantLock(); public void method() { lock.lock(); // 手動加鎖 try { // 臨界區(qū)代碼 } finally { lock.unlock(); // 必須手動釋放 } }
核心功能:
嘗試非阻塞獲取鎖:
tryLock()
。超時獲取鎖:
tryLock(long timeout, TimeUnit unit)
。公平性選擇:構(gòu)造函數(shù)傳入
true
實現(xiàn)公平鎖(按等待順序分配鎖)。條件變量:配合
Condition
實現(xiàn)線程間協(xié)調(diào)(如生產(chǎn)者-消費者模型)。
優(yōu)缺點:
優(yōu)點:靈活,支持中斷、超時、公平鎖。
缺點:需手動釋放鎖,編碼不當(dāng)易導(dǎo)致死鎖。
適用場景:
需要復(fù)雜同步控制的場景,如多條件等待、鎖超時處理。
3. ReadWriteLock(讀寫鎖)
作用:
允許多個線程同時讀,但寫線程獨占資源,適用于讀多寫少的場景。
實現(xiàn)類:ReentrantReadWriteLock
。
使用方式:
ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock(); ReentrantReadWriteLock.ReadLock readLock = rwLock.readLock(); ReentrantReadWriteLock.WriteLock writeLock = rwLock.writeLock(); public void readData() { readLock.lock(); try { ... } finally { readLock.unlock(); } } public void writeData() { writeLock.lock(); try { ... } finally { writeLock.unlock(); } }
特點:
讀共享:多個讀線程可同時訪問。
寫?yīng)氄?/strong>:寫線程獲取鎖時,禁止其他讀/寫操作。
鎖降級:寫鎖可降級為讀鎖(反之不可)。
適用場景:
緩存系統(tǒng)、頻繁讀取但偶爾更新的數(shù)據(jù)結(jié)構(gòu)。
4. StampedLock(Java 8+)
作用:
提供更靈活的讀寫鎖控制,支持樂觀讀、悲觀讀、寫鎖三種模式,性能優(yōu)于 ReadWriteLock
。
使用方式:
StampedLock stampedLock = new StampedLock(); // 樂觀讀(無鎖) long stamp = stampedLock.tryOptimisticRead(); if (!stampedLock.validate(stamp)) { // 檢查是否發(fā)生寫操作 stamp = stampedLock.readLock(); // 退化為悲觀讀 try { ... } finally { stampedLock.unlockRead(stamp); } } // 寫鎖 long writeStamp = stampedLock.writeLock(); try { ... } finally { stampedLock.unlockWrite(writeStamp); }
特點:
樂觀讀:假設(shè)沒有寫操作,通過
validate()
驗證。鎖轉(zhuǎn)換:支持讀鎖與寫鎖的轉(zhuǎn)換(如
tryConvertToWriteLock()
)。
適用場景:
讀多寫少且對性能要求極高的場景,但需謹(jǐn)慎處理鎖轉(zhuǎn)換邏輯。
5. 顯式鎖 vs 隱式鎖
維度 | 顯式鎖(如 ReentrantLock) | 隱式鎖(synchronized) |
---|---|---|
鎖獲取方式 | 手動調(diào)用 lock() 和 unlock() | 自動獲取和釋放 |
靈活性 | 支持超時、中斷、公平鎖、條件變量 | 僅支持非公平鎖,無超時或中斷機(jī)制 |
性能 | 高并發(fā)場景下更優(yōu) | 優(yōu)化后性能接近顯式鎖(如鎖升級機(jī)制) |
代碼復(fù)雜度 | 需手動管理,易出錯 | 自動管理,代碼簡潔 |
6. 鎖優(yōu)化策略(JVM 對 synchronized 的優(yōu)化)
偏向鎖:
假設(shè)只有一個線程訪問同步塊,通過標(biāo)記線程 ID 避免 CAS 操作。
適用場景:單線程重復(fù)訪問同步代碼。輕量級鎖:
當(dāng)多線程競爭時,通過 CAS 自旋嘗試獲取鎖(避免阻塞)。
適用場景:低競爭、同步塊執(zhí)行時間短。重量級鎖:
競爭激烈時,線程進(jìn)入阻塞狀態(tài),依賴操作系統(tǒng)的互斥量(Mutex)管理。
適用場景:高競爭、同步塊執(zhí)行時間長。
鎖升級流程:
無鎖 → 偏向鎖 → 輕量級鎖 → 重量級鎖
7. 條件鎖(Condition)
作用:
配合顯式鎖(如 ReentrantLock
)使用,實現(xiàn)線程的等待/喚醒機(jī)制,類似 Object.wait()
和 Object.notify()
,但更靈活。
使用方式:
ReentrantLock lock = new ReentrantLock(); Condition condition = lock.newCondition(); public void await() throws InterruptedException { lock.lock(); try { condition.await(); // 釋放鎖并等待 } finally { lock.unlock(); } } public void signal() { lock.lock(); try { condition.signal(); // 喚醒一個等待線程 } finally { lock.unlock(); } }
適用場景:
生產(chǎn)者-消費者模型、多條件線程協(xié)調(diào)。
8. 分布式鎖
作用:
在分布式系統(tǒng)中協(xié)調(diào)多節(jié)點對共享資源的訪問,防止并發(fā)沖突。
實現(xiàn)方式:
Redis:通過
SETNX
(或 RedLock 算法)實現(xiàn)。// 使用 Redisson 客戶端 RLock lock = redisson.getLock("myLock"); lock.lock(); try { ... } finally { lock.unlock(); }
ZooKeeper:通過臨時有序節(jié)點實現(xiàn)。
數(shù)據(jù)庫:利用唯一索引或樂觀鎖(版本號)。
核心挑戰(zhàn):
死鎖預(yù)防:設(shè)置鎖超時時間。
容錯性:避免單點故障(如 Redis 集群)。
總結(jié)
鎖類型 | 核心特點 | 適用場景 |
---|---|---|
synchronized | 簡單、自動管理,支持鎖升級優(yōu)化 | 簡單同步需求 |
ReentrantLock | 靈活,支持超時、公平鎖、條件變量 | 復(fù)雜同步控制(如多條件等待) |
ReadWriteLock | 讀寫分離,讀多寫少場景性能更優(yōu) | 緩存、頻繁讀的數(shù)據(jù)結(jié)構(gòu) |
StampedLock | 高性能,支持樂觀讀 | 極高并發(fā)讀場景 |
分布式鎖 | 跨進(jìn)程、跨節(jié)點協(xié)調(diào) | 分布式系統(tǒng)資源共享 |
選擇建議:
優(yōu)先使用
synchronized
(簡單場景)。需要靈活控制時選
ReentrantLock
。讀多寫少用
ReadWriteLock
或StampedLock
。分布式環(huán)境用 Redis/ZooKeeper 實現(xiàn)分布式鎖。
到此這篇關(guān)于Java中有哪些鎖的文章就介紹到這了,更多相關(guān)Java有哪些鎖內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringAOP+RabbitMQ+WebSocket實戰(zhàn)詳解
這篇文章主要介紹了SpringAOP+RabbitMQ+WebSocket實戰(zhàn)詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-11-11使用maven開發(fā)springboot項目時pom.xml常用配置(推薦)
這篇文章主要介紹了使用maven開發(fā)springboot項目時的pom.xml常用配置,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-01-01java編程FinalReference與Finalizer原理示例詳解
這篇文章主要為大家介紹了java編程FinalReference與Finalizer的核心原理以及示例源碼的分析詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助2022-01-01