java?讀寫鎖的使用及它的優(yōu)點(diǎn)
前言:
讀寫鎖(Readers-Writer Lock)顧名思義是一把鎖分為兩部分:讀鎖和寫鎖,其中讀鎖允許多個(gè)線程同時(shí)獲得,因?yàn)樽x操作本身是線程安全的,而寫鎖則是互斥鎖,不允許多個(gè)線程同時(shí)獲得寫鎖,并且寫操作和讀操作也是互斥的??偨Y(jié)來說,讀寫鎖的特點(diǎn)是:讀讀不互斥、讀寫互斥、寫寫互斥。
1.讀寫鎖使用
在 Java 語言中,讀寫鎖是使用 ReentrantReadWriteLock 類來實(shí)現(xiàn)的,其中:
ReentrantReadWriteLock.ReadLock
表示讀鎖,它提供了 lock 方法進(jìn)行加鎖、unlock 方法進(jìn)行解鎖。ReentrantReadWriteLock.WriteLock
表示寫鎖,它提供了 lock 方法進(jìn)行加鎖、unlock 方法進(jìn)行解鎖。
它的基礎(chǔ)使用如下代碼所示:
// 創(chuàng)建讀寫鎖 final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock(); // 獲得讀鎖 final ReentrantReadWriteLock.ReadLock readLock = readWriteLock.readLock(); // 獲得寫鎖 final ReentrantReadWriteLock.WriteLock writeLock = readWriteLock.writeLock(); // 讀鎖使用 readLock.lock(); try { // 業(yè)務(wù)代碼... } finally { readLock.unlock(); } // 寫鎖使用 writeLock.lock(); try { // 業(yè)務(wù)代碼... } finally { writeLock.unlock(); }
1.1 讀讀不互斥
多個(gè)線程可以同時(shí)獲取到讀鎖,稱之為讀讀不互斥,如下代碼所示:
// 創(chuàng)建讀寫鎖 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 讀寫互斥
讀鎖和寫鎖同時(shí)使用是互斥的(也就是不能同時(shí)獲得),這稱之為讀寫互斥,如下代碼所示:
// 創(chuàng)建讀寫鎖 final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock(); // 創(chuàng)建讀鎖 final ReentrantReadWriteLock.ReadLock readLock = readWriteLock.readLock(); // 創(chuàng)建寫鎖 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(); // 使用寫鎖 Thread t2 = new Thread(() -> { writeLock.lock(); try { System.out.println("[t2]得到寫鎖."); Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } finally { System.out.println("[t2]釋放寫鎖."); writeLock.unlock(); } }); t2.start();
以上程序執(zhí)行結(jié)果如下:
1.3 寫寫互斥
多個(gè)線程同時(shí)使用寫鎖也是互斥的,這稱之為寫寫互斥,如下代碼所示:
// 創(chuàng)建讀寫鎖 final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock(); // 創(chuàng)建寫鎖 final ReentrantReadWriteLock.WriteLock writeLock = readWriteLock.writeLock(); Thread t1 = new Thread(() -> { writeLock.lock(); try { System.out.println("[t1]得到寫鎖."); Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } finally { System.out.println("[t1]釋放寫鎖."); writeLock.unlock(); } }); t1.start(); Thread t2 = new Thread(() -> { writeLock.lock(); try { System.out.println("[t2]得到寫鎖."); Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } finally { System.out.println("[t2]釋放寫鎖."); writeLock.unlock(); } }); t2.start();
以上程序執(zhí)行結(jié)果如下:
2.優(yōu)點(diǎn)分析
- 提高了程序執(zhí)行性能:多個(gè)讀鎖可以同時(shí)執(zhí)行,相比于普通鎖在任何情況下都要排隊(duì)執(zhí)行來說,讀寫鎖提高了程序的執(zhí)行性能。
- 避免讀到臨時(shí)數(shù)據(jù):讀鎖和寫鎖是互斥排隊(duì)執(zhí)行的,這樣可以保證了讀取操作不會(huì)讀到寫了一半的臨時(shí)數(shù)據(jù)。
3.適用場景
讀寫鎖適合多讀少寫的業(yè)務(wù)場景,此時(shí)讀寫鎖的優(yōu)勢最大。
總結(jié)
讀寫鎖是一把鎖分為兩部分:讀鎖和寫鎖,其中讀鎖允許多個(gè)線程同時(shí)獲得,而寫鎖則是互斥鎖。它的完整規(guī)則是:讀讀不互斥、讀寫互斥、寫寫互斥。它適用于多讀的業(yè)務(wù)場景,使用它可以有效的提高程序的執(zhí)行性能,也能避免讀取到操作了一半的臨時(shí)數(shù)據(jù)。
到此這篇關(guān)于java 讀寫鎖的使用及它的優(yōu)點(diǎn)的文章就介紹到這了,更多相關(guān)Java讀寫鎖內(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,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-06-06SpringCloud 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-11SpringCloud微服務(wù)剔除下線功能實(shí)現(xiàn)原理分析
SpringCloud是一種微服務(wù)的框架,利用它我們可以去做分布式服務(wù)開發(fā),這篇文章主要介紹了SpringCloud微服務(wù)剔除下線功能,需要的朋友可以參考下2022-11-11淺談異常結(jié)構(gòu)圖、編譯期異常和運(yùn)行期異常的區(qū)別
下面小編就為大家?guī)硪黄獪\談異常結(jié)構(gòu)圖、編譯期異常和運(yùn)行期異常的區(qū)別。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-09-09Spring Boot整合QueryDSL的實(shí)現(xiàn)示例
這篇文章主要介紹了Spring Boot整合QueryDSL的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09springboot做代理分發(fā)服務(wù)+代理鑒權(quán)的實(shí)現(xiàn)過程
這篇文章主要介紹了springboot做代理分發(fā)服務(wù)+代理鑒權(quán)的實(shí)現(xiàn)過程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-01-01