有沒有比讀寫鎖更快的鎖

在之前的文章中,我們介紹了讀寫鎖,學習完之后你應該已經知道了讀寫鎖允許多個線程同時訪問共享變量,適用于讀多寫少的場景。那么在讀多寫少的場景中還有沒有更快的技術方案呢?還真有,在Java1.8這個版本里提供了一種叫StampedLock的鎖,它的性能就比讀寫鎖還要好。
下面我們介就來介紹一下StampedLock的使用方法、內部工作原理以及在使用過程中需要注意的事項。

StampedLock支持的三種模式

我們先來看看StampedLock在使用什么,和上篇文章中的ReadWriteLock所有哪些區別。
ReadWriteLock支持兩種模式,一種是讀鎖,一種是寫鎖,而StampedLock支持三種模式,分別是寫鎖、悲觀鎖鎖、樂觀讀,其中寫鎖、悲觀讀鎖的語義和ReadWriteLock的寫鎖、讀鎖的語義非常類似。允許多個線程同時獲取悲觀讀鎖,但是只允許一個線程獲取寫鎖,寫鎖和悲觀讀鎖都是互斥的,然而不同的是里面的寫鎖和悲觀讀鎖加鎖成功之后,都會返回一個stamp。然后解鎖的時候需要傳入這個stamp。相關的實例代碼如下。

final StampedLock sl = new StampedLock();//獲取/釋放悲觀讀鎖示意代碼
long stamp = sl.reaLock();
try{//省略業務代碼
} finally {sl.unlockRead(stamp);
}//獲取/釋放寫鎖示意代碼
long stamp = sl.writeLock();
try{//省略相關業務代碼
} finally {sl.unlockWrite(stamp);
}

StampedLock 的性能之所以比ReadWriteLock還要好,關鍵是StampedLock支持樂觀讀的方式。ReadWriteLock支持多個線程同時讀,但是當多個線程同時讀的時候,所有的寫操作也會被阻塞。而StampedLock提供的樂觀讀是允許一個線程獲取寫鎖的,也就是說不是所有寫操作都被阻塞的。
注意,這里我們用的是"樂觀讀"這個詞,而不是樂觀讀鎖,是要提醒你,樂觀讀操作是無鎖的,所以相比較ReadWriteLock的讀鎖,樂觀讀的性能更好一點。文中下面這段代碼是出自于Java SDK官方示例,并略作修改。在distanceFromRrigin()這個方法中,首先通過調用tryOptimisticRead獲得了一個stamp。這里的tryOptimisticRead就是我們前面提到的樂觀讀。之后將共享變量X和Y讀入方法的局部變量中。不過需要注意的是,由于tryOptimisticRead是無鎖的,所以共享變量X和Y讀入方法局部變量時,X和Y有可能被其他線程修改了,因此最后讀完之后還需要再次驗證一下是否存在寫操作,這個操作是通過調用validate (stamp)來實現的。

class Point {private int x,y;final StampedLock sl = new StampedLock();//計算到原點的距離int distanceFromOrigin(){//樂觀讀long stamp = sl.tryOptimisticRead();//讀入局部變量//讀的過程中數據可能被修改int curX = x,curY = y;//判斷執行讀操作期間,是否存在寫操作//如果存在,返回falseif(!sl.validate(stamp)){//升級為悲觀鎖stamp = sl.readLock();try{curX = x;curY = y;} finally {sl.unLockRead(stamp);}}return Math.sqrt(curX * curX + curY * curY);}
}

在上面這個代碼示例中,如果執行樂觀讀操作期間存在寫操作,會把樂觀讀升級為悲觀讀鎖。這個做法挺合理的,否則你就需要在一個循環里反復執行樂觀讀,直到執行樂觀讀操作期間沒有寫操作,只有這樣才能保證X和Y的正確性和一致性。而循環讀會浪費大量的CPU。升級為悲觀讀鎖代碼簡練且不易出錯,建議你在具體實踐的時候也采用這樣的方法。

進一步理解樂觀讀

如果你曾經用過數據庫的樂觀鎖,你可能會發現StampLock的樂觀讀和數據庫的樂觀讀鎖有異曲同工之妙。的確是這樣的,就我個人而言,我是先接觸數據庫的樂觀鎖,然后再接觸的StampLock,我就覺得我前期數據庫里的樂觀鎖的學習,對于后面的理解StampLock的樂觀讀有很大的幫助,所以這里有必要再介紹一下數據庫里的樂觀鎖。
還記得我第一次使用數據庫樂觀鎖的場景是這樣的,在ERP的生產模塊里,會有多個人通過ERP系統提供的UI同時修改同一條生產訂單,那如何保證生產訂單數據是并發安全的呢?我采用的方案就是樂觀鎖。
樂觀鎖的實現很簡單,在生產訂單的表product_doc里面增加一個數字型的版本號字段version,每次更新product_doc這個表的時候,都將version字段加1。生產訂單的UI在展示的時候需要查詢數據庫。此時將這個version字段和其他業務字段一起返回給生產訂單UI。假設用戶查詢的生產訂單的ID=777,那么SQL語句類似于下面這樣。

select id,....,version
from product_doc
where id = 777

用戶在生產訂單UI執行保存操作時候,后臺利用下面的SQL語句更新生產訂單,此時我們假設該條生產訂單的version等于9。

update product_doc
set version=version+1
where id=777 and versoin=9

如果這條語SQL語句成執行成功,并且返回的條數等于1,那么說明從生產訂單UI執行查詢操作到執行保存操作期間沒有其他人修改過這條數據。因為如果這期間其他人修改過這條數據,那么版本號一定會大于9。
你會發現數據庫里的樂觀鎖查詢的時候需要把version字段查出來,更新的時候要利用version字段做校驗,這個version字段就類似于StampLock里面的stamp,這樣對比著看,你相信你會更容易理解StampLock里面樂觀讀的用法。

StampLock使用注意事項

對于讀多寫少的場景StampLock性能很好,簡單的應用場景基本上可以替代ReadWriteLock,但是StampLock的功能僅僅是ReadWriteLock的子集,在使用的時候還是有幾個需地方需要注意一下。
StampLock在命名上并沒有增加Reentrant,想必你已經猜到了,StampLock應該是不可重入的,事實上的確是這樣的,StampLock不支持重入,這個是在使用中必須要注意的。
另外StampLock的悲觀讀鎖、寫鎖都不支持條件變量,這個你也需要注意。
還有一點需要特別注意,那就是如果線程阻塞在StampLock的readLock()上時,此時調用該阻塞線程的interrupt()方法會導致CPU飆升。
所以使用StampLock一定不要調用中斷操作,如果需要支持中斷功能,一定使用可中斷的悲觀讀鎖readLockInterruptibly()和寫鎖writeLockInterruptibly(),這個規則一定要記清楚。

總結

StampLock的使用看上去有點復雜,但是如果你能理解樂觀所背后的原理,使用起來還是比較流暢的。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/41337.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/41337.shtml
英文地址,請注明出處:http://en.pswp.cn/news/41337.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Docker安裝Skywalking APM分布式追蹤系統

Skywalking是一個應用性能管理(APM)系統,具有服務器性能監測,應用程序間調用關系及性能監測等功能,Skywalking分為服務端、管理界面、以及嵌入到程序中的探針部分,由程序中的探針采集各類調用數據發送給服務端保存,在管…

novnc 和 vnc server 如何實現通信?原理?

參考:https://www.codenong.com/js0f3b351a156c/

隨機微分方程

應用隨機過程|第7章 隨機微分方程 見知乎:https://zhuanlan.zhihu.com/p/348366892?utm_sourceqq&utm_mediumsocial&utm_oi1315073218793488384

復習3-5天【80天學習完《深入理解計算機系統》】第七天

專注 效率 記憶 預習 筆記 復習 做題 歡迎觀看我的博客,如有問題交流,歡迎評論區留言,一定盡快回復!(大家可以去看我的專欄,是所有文章的目錄)   文章字體風格: 紅色文字表示&#…

Linux與bash(基礎內容一)

一、常見的linux命令: 1、文件: (1)常見的文件命令: (2)文件屬性: (3)修改文件屬性: 查看文件的屬性: ls -l 查看文件的屬性 ls …

神經網絡基礎-神經網絡補充概念-33-偏差與方差

概念 偏差(Bias): 偏差是模型預測值與實際值之間的差距,它反映了模型對訓練數據的擬合能力。高偏差意味著模型無法很好地擬合訓練數據,通常會導致欠擬合。欠擬合是指模型過于簡單,不能捕捉數據中的復雜模式…

基于java在線讀書與分享論壇設計與實現

摘 要 互聯系統的技術在如今的社會中,應用的越來越廣泛,通過互聯系統我們可以更方便地進行辦公,也能夠在系統上就能處理很多日常的事務。互聯系統的技術的發展,也是人們日常中接觸更多的一項技術。隨著互聯系統的發展,…

Swin Transformer: Hierarchical Vision Transformer using Shifted Windows

Swin Transformer: Hierarchical Vision Transformer using Shifted Windows 摘要當前的檢測sota模型網絡架構swin Transformer和Vision Transformer的不同之處整體架構Patch Partition結構Linear Embedding結構Swin Transformer Block結構 Patch MergingW-MSAMSA模塊計算量W-M…

學習Vue:Vue3 VS Vue2

Vue 3作為Vue.js的最新版本,帶來了一系列令人激動的新特性和改進,讓開發者們在構建現代Web應用時體驗更加順暢和高效。本文將全面介紹Vue 3相對于Vue 2的改進,重點解釋Composition API的使用,以及新引入的Teleport和Suspense等特性…

Genoss GPT簡介:使用 Genoss 模型網關實現多個LLM模型的快速切換與集成

一、前言 生成式人工智能領域的發展繼續加速,大型語言模型 (LLM) 的用途范圍不斷擴大。這些用途跨越不同的領域,包括個人助理、文檔檢索以及圖像和文本生成。ChatGPT 等突破性應用程序為公司進入該領域并開始使用這項技術進行構建鋪平了道路。 大公司正…

如何發布自己的小程序

小程序的基礎內容組件 text&#xff1a; 文本支持長按選中的效果 <text selectable>151535313511</text> rich-text: 把HTML字符串渲染為對應的UI <rich-text nodes"<h1 stylecolor:red;>123</h1>"></rich-text> 小程序的…

MySql過濾重復數據

假設模型表是: 1. 根據單字段過濾: SELECT user_name, COUNT(*) as count FROM sys_user GROUP BY user_name HAVING count > 1;結果: 2. 根據多個字段查詢重復數據 SELECT user_name, email, COUNT(*) as count FROM sys_user GROUP BY user_name, email HAVING count…

[centos]設置主機名

1、設置 hostnamectl set-hostname 名字 2、查看是否生效 hostnamectl status 3、打開一個新鏈接就可以了

log4j教程_編程入門自學教程_菜鳥教程-免費教程分享

教程簡介 Log4j是Apache的一個開源項目&#xff0c;通過使用Log4j&#xff0c;我們可以控制日志信息輸送的目的地是控制臺、文件、GUI組件&#xff0c;甚至是套接口服務器、NT的事件記錄器、UNIX Syslog守護進程等&#xff1b;我們也可以控制每一條日志的輸出格式&#xff1b;…

[python] 使用Jieba工具中文分詞及文本聚類概念

前面講述了很多關于Python爬取本體Ontology、消息盒InfoBox、虎撲圖片等例子&#xff0c;同時講述了VSM向量空間模型的應用。但是由于InfoBox沒有前后文和語義概念&#xff0c;所以效果不是很好&#xff0c;這篇文章主要是爬取百度5A景區摘要信息&#xff0c;再利用Jieba分詞工…

hive--給表名和字段加注釋

1.建表添加注釋 CREATE EXTERNAL TABLE test(loc_province string comment 省份,loc_city string comment 城市,loc_district string comment 區,loc_street string comment 街道,)COMMENT 每日數據處理后的表 PARTITIONED BY (par_dt string) ROW FORMAT SERDEorg.apache.had…

學習Vue:響應式原理與性能優化策略

性能優化是Vue.js應用開發中的一個關鍵方面&#xff0c;而深入了解響應式原理并采用有效的性能優化策略可以顯著提升應用的性能。本文將解釋響應式原理并介紹一些性能優化策略&#xff0c;旨在幫助您構建高性能的Vue.js應用。 響應式原理 Vue.js的響應式原理是通過利用Object.…

PHP在線客服系統推薦

在當今數字化時代&#xff0c;企業客戶服務的重要性不容忽視。為了提供卓越的客戶體驗&#xff0c;許多企業正在尋找PHP在線客服系統。這種系統不僅可以滿足客戶的需求&#xff0c;還能提升企業的形象。本文將深入探討PHP在線客服系統的一些有趣話題。 理解PHP在線客服系統 PHP…

71 # 協商緩存的配置:通過內容

對比&#xff08;協商&#xff09;緩存 比較一下再去決定是用緩存還是重新獲取數據&#xff0c;這樣會減少網絡請求&#xff0c;提高性能。 對比緩存的工作原理 客戶端第一次請求服務器的時候&#xff0c;服務器會把數據進行緩存&#xff0c;同時會生成一個緩存標識符&#…

Transformer是什么,Transformer應用

目錄 Transformer應用 Transformer是什么 Transformer應用:循環神經網絡 語言翻譯:注重語句前后順序 RNN看中單個特征; CNN:看中特征之間時序性 模型關注不同位置的能力 Transformer是什么 Transformer是一個利用注意力機制來提高模型訓練速度的模型。關于注意力機…