Java中的ReadWriteLock讀寫鎖詳解
ReadWriteLock
ReadWriteLock也是一個(gè)接口,提供了readLock和writeLock兩種鎖的操作機(jī)制,一個(gè)資源可以被多個(gè)線程同時(shí)讀,或者被一個(gè)線程寫,但是不能同時(shí)存在讀和寫線程。
讀鎖:共享鎖 readLock
**寫鎖:**獨(dú)占鎖 writeLock
讀寫鎖 : 一個(gè)資源可以被多個(gè)讀的線程進(jìn)行訪問 ,或者可以被一個(gè)寫的線程訪問,
但是不能同時(shí)存在讀和寫進(jìn)程 ,讀寫互斥,讀讀共享。
讀的時(shí)候可以多個(gè)線程一起讀
寫的時(shí)候只能一個(gè)線程寫
使用示例:
向map中添加和讀取值
public class ReadWriteLock {
public static void main(String[] args) {
MyCache myCache = new MyCache();
//十個(gè)寫線程
for (int i = 0; i < 10; i++) {
final int temp=i;
new Thread(() -> {
myCache.put(temp+"",temp+"");
}, String.valueOf(i)).start();
}
//十個(gè)讀線程
for (int i = 0; i < 10; i++) {
final int temp=i;
new Thread(() -> {
myCache.get(temp+"");
}, String.valueOf(i)).start();
}
}
}
/**
* 自定義緩存
*/
class MyMap {
private volatile Map<String, Object> map = new HashMap<>();
//存入值
public void put(String key, Object value) {
System.out.println(Thread.currentThread().getName() + "寫入" + key);
map.put(key, value);
System.out.println(Thread.currentThread().getName() + "寫入完成");
}
//取值
public void get(String key) {
System.out.println(Thread.currentThread().getName() + "讀取" + key);
Object o = map.get(key);
System.out.println(Thread.currentThread().getName() + "讀取完成");
}
}我們可以看到1寫入跟寫入完成之間插入了4線程 這是不對(duì)的

于是我們加入讀寫鎖
加鎖
lock.writeLock().lock(); lock.readLock().lock();
解鎖
lock.writeLock().unlock(); lock.readLock().unlock();
class MyCacheLock {
private volatile Map<String, Object> map = new HashMap<>();
//讀寫鎖 :更加細(xì)粒度的控制
private ReadWriteLock lock = new ReentrantReadWriteLock();
//存入值 寫的時(shí)候只希望同時(shí)只有一個(gè)線程寫
public void put(String key, Object value) {
//加寫鎖
lock.writeLock().lock();
try {
System.out.println(Thread.currentThread().getName() + "寫入" + key);
map.put(key, value);
System.out.println(Thread.currentThread().getName() + "寫入完成");
} catch (Exception e) {
} finally {
lock.writeLock().unlock();
}
}
//取值 讀所有人都可以讀
public void get(String key) {
//加讀鎖
lock.readLock().lock();
try {
System.out.println(Thread.currentThread().getName() + "讀取" + key);
Object o = map.get(key);
System.out.println(Thread.currentThread().getName() + "讀取完成");
} catch (Exception e) {
} finally {
lock.readLock().unlock();
}
}
}
讀寫鎖的演變
一、無鎖
無鎖狀態(tài)多線程搶占資源 會(huì)出現(xiàn)問題
二、加鎖
synchronized和reentrantLock
都是獨(dú)占鎖 每次只能一個(gè)線程來操作
讀讀 一個(gè)線程 只能一個(gè)人讀
讀寫 一個(gè)線程
寫寫 一個(gè)線程
三、讀寫鎖
ReentrantReadWriteLock
讀讀可以共享,提升性能 同時(shí)多人讀
寫寫 一個(gè)線程
缺點(diǎn):
1.造成鎖的饑餓,可能一直讀沒有寫的操作
2.寫的時(shí)候,自己線程可以讀,讀的時(shí)候,哪個(gè)線程都不可以寫
鎖降級(jí)
鎖降級(jí):將寫入鎖降級(jí)為讀鎖 讀鎖不能升級(jí)為寫鎖
獲取寫鎖—>獲取讀鎖—>釋放寫鎖—>釋放讀鎖
示例
public class Downgrade {
public static void main(String[] args) {
//可重入讀寫鎖對(duì)象
ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
//讀鎖
ReentrantReadWriteLock.ReadLock readLock = lock.readLock();
//寫鎖
ReentrantReadWriteLock.WriteLock writeLock = lock.writeLock();
//鎖降級(jí)
//獲取寫鎖
writeLock.lock();
System.out.println("飛飛");
//獲取讀鎖
readLock.lock();
System.out.println("read讀取");
//解鎖
writeLock.unlock();
readLock.unlock();
}
}
但是我們不可以在讀鎖中獲取寫鎖
示例2:
public class Downgrade {
public static void main(String[] args) {
//可重入讀寫鎖對(duì)象
ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
//讀鎖
ReentrantReadWriteLock.ReadLock readLock = lock.readLock();
//寫鎖
ReentrantReadWriteLock.WriteLock writeLock = lock.writeLock();
//鎖降級(jí)
//獲取讀鎖
readLock.lock();
System.out.println("read讀取");
//獲取寫鎖
writeLock.lock();
System.out.println("飛飛");
//解鎖
writeLock.unlock();
readLock.unlock();
}
}
不可以在讀鎖中寫 不會(huì)停止
到此這篇關(guān)于Java中的ReadWriteLock讀寫鎖詳解的文章就介紹到這了,更多相關(guān)ReadWriteLock讀寫鎖內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java比較器Comparable接口與Comaprator接口的深入分析
本篇文章是對(duì)java比較器Comparable接口與Comaprator接口進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-06-06
jar包在windows后臺(tái)運(yùn)行,通過.bat文件實(shí)現(xiàn)
文章主要講解了在Windows后臺(tái)運(yùn)行JAR包的方法,通過創(chuàng)建啟動(dòng).bat和停止.bat文件,使用javaw方式運(yùn)行JAR包,可以在關(guān)閉cmd界面后仍然保持程序運(yùn)行,提供了啟動(dòng).bat和停止.bat的具體內(nèi)容2026-04-04
一文詳解Redisson分布式鎖底層實(shí)現(xiàn)原理
這篇文章主要詳細(xì)介紹了Redisson分布式鎖底層實(shí)現(xiàn)原理,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-07-07
使用Spring從YAML文件讀取內(nèi)容映射為Map方式
這篇文章主要介紹了使用Spring從YAML文件讀取內(nèi)容映射為Map方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-02-02
淺談Spring Cloud Eureka 自我保護(hù)機(jī)制
這篇文章主要介紹了淺談Spring Cloud Eureka 自我保護(hù)機(jī)制,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-06-06

