java?讀寫(xiě)鎖的使用及它的優(yōu)點(diǎn)
前言:
讀寫(xiě)鎖(Readers-Writer Lock)顧名思義是一把鎖分為兩部分:讀鎖和寫(xiě)鎖,其中讀鎖允許多個(gè)線程同時(shí)獲得,因?yàn)樽x操作本身是線程安全的,而寫(xiě)鎖則是互斥鎖,不允許多個(gè)線程同時(shí)獲得寫(xiě)鎖,并且寫(xiě)操作和讀操作也是互斥的??偨Y(jié)來(lái)說(shuō),讀寫(xiě)鎖的特點(diǎn)是:讀讀不互斥、讀寫(xiě)互斥、寫(xiě)寫(xiě)互斥。
1.讀寫(xiě)鎖使用
在 Java 語(yǔ)言中,讀寫(xiě)鎖是使用 ReentrantReadWriteLock 類來(lái)實(shí)現(xiàn)的,其中:
ReentrantReadWriteLock.ReadLock表示讀鎖,它提供了 lock 方法進(jìn)行加鎖、unlock 方法進(jìn)行解鎖。ReentrantReadWriteLock.WriteLock表示寫(xiě)鎖,它提供了 lock 方法進(jìn)行加鎖、unlock 方法進(jìn)行解鎖。
它的基礎(chǔ)使用如下代碼所示:
// 創(chuàng)建讀寫(xiě)鎖
final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
// 獲得讀鎖
final ReentrantReadWriteLock.ReadLock readLock = readWriteLock.readLock();
// 獲得寫(xiě)鎖
final ReentrantReadWriteLock.WriteLock writeLock = readWriteLock.writeLock();
// 讀鎖使用
readLock.lock();
try {
// 業(yè)務(wù)代碼...
} finally {
readLock.unlock();
}
// 寫(xiě)鎖使用
writeLock.lock();
try {
// 業(yè)務(wù)代碼...
} finally {
writeLock.unlock();
}1.1 讀讀不互斥
多個(gè)線程可以同時(shí)獲取到讀鎖,稱之為讀讀不互斥,如下代碼所示:
// 創(chuàng)建讀寫(xiě)鎖
final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
// 創(chuàng)建讀鎖
final ReentrantReadWriteLock.ReadLock readLock = readWriteLock.readLock();
Thread t1 = new Thread(() -> {
readLock.lock();
try {
System.out.println("[t1]得到讀鎖.");
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println("[t1]釋放讀鎖.");
readLock.unlock();
}
});
t1.start();
Thread t2 = new Thread(() -> {
readLock.lock();
try {
System.out.println("[t2]得到讀鎖.");
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println("[t2]釋放讀鎖.");
readLock.unlock();
}
});
t2.start();以上程序執(zhí)行結(jié)果如下:

1.2 讀寫(xiě)互斥
讀鎖和寫(xiě)鎖同時(shí)使用是互斥的(也就是不能同時(shí)獲得),這稱之為讀寫(xiě)互斥,如下代碼所示:
// 創(chuàng)建讀寫(xiě)鎖
final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
// 創(chuàng)建讀鎖
final ReentrantReadWriteLock.ReadLock readLock = readWriteLock.readLock();
// 創(chuàng)建寫(xiě)鎖
final ReentrantReadWriteLock.WriteLock writeLock = readWriteLock.writeLock();
// 使用讀鎖
Thread t1 = new Thread(() -> {
readLock.lock();
try {
System.out.println("[t1]得到讀鎖.");
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println("[t1]釋放讀鎖.");
readLock.unlock();
}
});
t1.start();
// 使用寫(xiě)鎖
Thread t2 = new Thread(() -> {
writeLock.lock();
try {
System.out.println("[t2]得到寫(xiě)鎖.");
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println("[t2]釋放寫(xiě)鎖.");
writeLock.unlock();
}
});
t2.start();以上程序執(zhí)行結(jié)果如下:

1.3 寫(xiě)寫(xiě)互斥
多個(gè)線程同時(shí)使用寫(xiě)鎖也是互斥的,這稱之為寫(xiě)寫(xiě)互斥,如下代碼所示:
// 創(chuàng)建讀寫(xiě)鎖
final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
// 創(chuàng)建寫(xiě)鎖
final ReentrantReadWriteLock.WriteLock writeLock = readWriteLock.writeLock();
Thread t1 = new Thread(() -> {
writeLock.lock();
try {
System.out.println("[t1]得到寫(xiě)鎖.");
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println("[t1]釋放寫(xiě)鎖.");
writeLock.unlock();
}
});
t1.start();
Thread t2 = new Thread(() -> {
writeLock.lock();
try {
System.out.println("[t2]得到寫(xiě)鎖.");
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println("[t2]釋放寫(xiě)鎖.");
writeLock.unlock();
}
});
t2.start();以上程序執(zhí)行結(jié)果如下:

2.優(yōu)點(diǎn)分析
- 提高了程序執(zhí)行性能:多個(gè)讀鎖可以同時(shí)執(zhí)行,相比于普通鎖在任何情況下都要排隊(duì)執(zhí)行來(lái)說(shuō),讀寫(xiě)鎖提高了程序的執(zhí)行性能。
- 避免讀到臨時(shí)數(shù)據(jù):讀鎖和寫(xiě)鎖是互斥排隊(duì)執(zhí)行的,這樣可以保證了讀取操作不會(huì)讀到寫(xiě)了一半的臨時(shí)數(shù)據(jù)。
3.適用場(chǎng)景
讀寫(xiě)鎖適合多讀少寫(xiě)的業(yè)務(wù)場(chǎng)景,此時(shí)讀寫(xiě)鎖的優(yōu)勢(shì)最大。
總結(jié)
讀寫(xiě)鎖是一把鎖分為兩部分:讀鎖和寫(xiě)鎖,其中讀鎖允許多個(gè)線程同時(shí)獲得,而寫(xiě)鎖則是互斥鎖。它的完整規(guī)則是:讀讀不互斥、讀寫(xiě)互斥、寫(xiě)寫(xiě)互斥。它適用于多讀的業(yè)務(wù)場(chǎng)景,使用它可以有效的提高程序的執(zhí)行性能,也能避免讀取到操作了一半的臨時(shí)數(shù)據(jù)。
到此這篇關(guān)于java 讀寫(xiě)鎖的使用及它的優(yōu)點(diǎn)的文章就介紹到這了,更多相關(guān)Java讀寫(xiě)鎖內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Idea Jrebel 報(bào)錯(cuò):Cannot reactivate,offline 
本文主要介紹了Idea Jrebel 報(bào)錯(cuò):Cannot reactivate,offline seat in use,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-06-06
SpringCloud openfeign相互調(diào)用實(shí)現(xiàn)方法介紹
在springcloud中,openfeign是取代了feign作為負(fù)載均衡組件的,feign最早是netflix提供的,他是一個(gè)輕量級(jí)的支持RESTful的http服務(wù)調(diào)用框架,內(nèi)置了ribbon,而ribbon可以提供負(fù)載均衡機(jī)制,因此feign可以作為一個(gè)負(fù)載均衡的遠(yuǎn)程服務(wù)調(diào)用框架使用2022-11-11
SpringCloud微服務(wù)剔除下線功能實(shí)現(xiàn)原理分析
SpringCloud是一種微服務(wù)的框架,利用它我們可以去做分布式服務(wù)開(kāi)發(fā),這篇文章主要介紹了SpringCloud微服務(wù)剔除下線功能,需要的朋友可以參考下2022-11-11
淺談異常結(jié)構(gòu)圖、編譯期異常和運(yùn)行期異常的區(qū)別
下面小編就為大家?guī)?lái)一篇淺談異常結(jié)構(gòu)圖、編譯期異常和運(yùn)行期異常的區(qū)別。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-09-09
Spring Boot整合QueryDSL的實(shí)現(xiàn)示例
這篇文章主要介紹了Spring Boot整合QueryDSL的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09
springboot做代理分發(fā)服務(wù)+代理鑒權(quán)的實(shí)現(xiàn)過(guò)程
這篇文章主要介紹了springboot做代理分發(fā)服務(wù)+代理鑒權(quán)的實(shí)現(xiàn)過(guò)程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-01-01

