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

