【多線程】常見鎖策略詳解(面試常考題型)

目錄

  • 🌴 樂觀鎖 vs 悲觀鎖
  • 🎍重量級鎖 vs 輕量級鎖
  • 🍀自旋鎖(Spin Lock)
  • 🎋公平鎖 vs ?公平鎖
  • 🌳可重?鎖 vs 不可重?鎖
  • 🎄讀寫鎖
  • ?相關面試題

常?的鎖策略

注意: 接下來講解的鎖策略不僅僅是局限于 Java . 任何和 “鎖” 相關的話題, 都可能會涉及到以下內容.
這些特性主要是給鎖的實現者來參考的.

普通的程序猿也需要了解?些, 對于合理的使?鎖也是有很?幫助的.

🌴 樂觀鎖 vs 悲觀鎖

悲觀鎖:
總是假設最壞的情況,每次去拿數據的時候都認為別?會修改,所以每次在拿數據的時候都會上鎖,
這樣別?想拿這個數據就會阻塞直到它拿到鎖。

樂觀鎖
假設數據?般情況下不會產?并發沖突,所以在數據進?提交更新的時候,才會正式對數據是否產?
并發沖突進?檢測,如果發現并發沖突了,則讓返回??錯誤的信息,讓??決定如何去做。

樂觀鎖的一個重要功能就是要檢測出數據是否發生訪問沖突.

那我們具體是怎么檢測的呢?這里我們我們可以引入一個 “版本號” 來解決.

那什么是版本號呢?請看下面的例子:
假設我們需要多線程修改 “用戶賬戶余額”.

設當前余額為 100. 引入一個版本號 version, 初始值為 1. 并且我們規定 "提交版本必須大于記錄當前版本”才能執行更新余額

接下來我們進行以下操作:

第一步:線程 A 此時準備將其讀出( version=1, balance=100 ),線程 B 也讀入此信息( version=1,balance=100 )
在這里插入圖片描述第二步:線程 A 操作的過程中并從其帳戶余額中扣除 50( 100-50 ),線程 B 從其帳戶余額中扣除 20( 100-20 );
在這里插入圖片描述
第三步:線程 A 完成修改工作,將數據版本號加1( version=2 ),連同帳戶扣除后余額( balance=50),寫回到內存中;
在這里插入圖片描述
第四步:線程 B 完成了操作,也將版本號加1( version=2 )試圖向內存中提交數據( balance=80),但此時比對版本發現,操作員 B 提交的數據版本號為 2 ,數據庫記錄的當前版本也為 2 ,不滿足 “提交版本必須大于記錄當前版本才能執行更新“ 的樂觀鎖策略。就認為這次操作失敗.
在這里插入圖片描述

在Java中,Synchronized 初始使?樂觀鎖策略. 當發現鎖競爭?較頻繁的時候, 就會?動切換成悲觀鎖策略.

🎍重量級鎖 vs 輕量級鎖

鎖的核?特性 “原?性”, 這樣的機制追根溯源是 CPU 這樣的硬件設備提供的.
? CPU 提供了 “原?操作指令”.
? 操作系統基于 CPU 的原?指令, 實現了 mutex 互斥鎖.
? JVM 基于操作系統提供的互斥鎖, 實現了 synchronized 和 ReentrantLock 等關鍵字和類.

在這里插入圖片描述
注意, synchronized 并不僅僅是對 mutex 進?封裝, 在 synchronized 內部還做了很多其
他的?作

重量級鎖: 加鎖機制重度依賴了 OS 提供了 mutex

? ?量的內核態??態切換
? 很容易引發線程的調度

這兩個操作, 成本?較?. ?旦涉及到??態和內核態的切換, 就意味著 “滄海桑?”.

輕量級鎖: 加鎖機制盡可能不使? mutex, ?是盡量在??態代碼完成. 實在搞不定了, 再使? mutex.

? 少量的內核態??態切換.
? 不太容易引發線程調度.

什么是用戶態什么是內核態

理解??態 vs 內核態 想象去銀?辦業務. 在窗?外, ??做, 這是??態. ??態的時間成本是?較可控的. 在窗?內, ?作?員做,
這是內核態. 內核態的時間成本是不太可控的. 如果辦業務的時候反復和?作?員溝通, 還需要重新排隊, 這時效率是很低的.

synchronized 開始是?個輕量級鎖. 如果鎖沖突比較嚴重, 就會變成重量級鎖.

🍀自旋鎖(Spin Lock)

按之前的?式,線程在搶鎖失敗后進?阻塞狀態,放棄 CPU,需要過很久才能再次被調度.

但實際上, ?部分情況下,雖然當前搶鎖失敗,但過不了很久,鎖就會被釋放。沒必要就放棄 CPU. 這個時候就可以使??旋鎖來處理這樣的問題.

?旋鎖偽代碼:

while (搶鎖(lock) == 失敗) {}

如果獲取鎖失敗, ?即再嘗試獲取鎖, ?限循環, 直到獲取到鎖為?. 第?次獲取鎖失敗, 第?次的嘗試會在極短的時間內到來.

?旦鎖被其他線程釋放, 就能第?時間獲取到鎖

理解?旋鎖 vs 掛起等待鎖
想象?下, 去追求?個?神. 當男?向?神表?后, ?神說: 你是個好?, 但是我有男朋友了~~
掛起等待鎖: 陷?沉淪不能?拔… 過了很久很久之后, 突然?神發來消息, “咱倆要不試試?” (注意, 這
個很?的時間間隔?, ?神可能已經換了好?個男票了).
?旋鎖: 死?賴臉堅韌不拔. 仍然每天持續的和?神說早安晚安. ?旦?神和上?任分?, 那么就能?刻
抓住機會上位.

==?旋鎖是?種典型的 輕量級鎖 的實現?式.
? 優點: 沒有放棄 CPU, 不涉及線程阻塞和調度, ?旦鎖被釋放, 就能第?時間獲取到鎖.
? 缺點: 如果鎖被其他線程持有的時間?較久, 那么就會持續的消耗 CPU 資源. (?掛起等待的時候是不消耗 CPU 的).

synchronized 中的輕量級鎖策略?概率就是通過?旋鎖的?式實現的.

🎋公平鎖 vs ?公平鎖

假設三個線程 A, B, C. A 先嘗試獲取鎖, 獲取成功. 然后 B 再嘗試獲取鎖, 獲取失敗, 阻塞等待; 然后 C
也嘗試獲取鎖, C 也獲取失敗, 也阻塞等待.

當線程 A 釋放鎖的時候, 會發?啥呢?

公平鎖: 遵守 “先來后到”. B ? C 先來的. 當 A 釋放鎖的之后, B 就能先于 C 獲取到鎖.

?公平鎖: 不遵守 “先來后到”. B 和 C 都有可能獲取到鎖.

這就好??群男?追同?個?神. 當?神和前任分?之后, 先來追?神的男?上位, 這就是公平鎖; 如果
是?神不按先后順序挑?個??看的順眼的, 就是?公平鎖.
在這里插入圖片描述

注意:

? 操作系統內部的線程調度就可以視為是隨機的. 如果不做任何額外的限制, 鎖就是?公平鎖. 如果要
想實現公平鎖, 就需要依賴額外的數據結構, 來記錄線程們的先后順序.

? 公平鎖和?公平鎖沒有好壞之分, 關鍵還是看適?場景.

synchronized 是?公平鎖.

🌳可重?鎖 vs 不可重?鎖

可重?鎖的字?意思是“可以重新進?的鎖”,即允許同?個線程多次獲取同?把鎖

?如?個遞歸函數?有加鎖操作,遞歸過程中這個鎖會阻塞??嗎?如果不會,那么這個鎖就是可重?鎖(因為這個原因可重?鎖也叫做遞歸鎖)。

Java?只要以Reentrant開頭命名的鎖都是可重?鎖,?且JDK提供的所有現成的Lock實現類,包括synchronized關鍵字鎖都是可重?的

? Linux 系統提供的 mutex 是不可重?鎖.

理解 “把??鎖死”
?個線程沒有釋放鎖, 然后?嘗試再次加鎖.

1 // 第?次加鎖, 加鎖成功
2 lock();
3 // 第?次加鎖, 鎖已經被占?, 阻塞等待. 
4 lock();

按照之前對于鎖的設定, 第?次加鎖的時候, 就會阻塞等待. 直到第?次的鎖被釋放, 才能獲取到第?個
鎖. 但是釋放第?個鎖也是由該線程來完成, 結果這個線程已經躺平了, 啥都不想?了, 也就?法進?解
鎖操作. 這時候就會 死鎖.

在這里插入圖片描述
這樣的鎖稱為 不可重?鎖.

最后,要記得

synchronized 是可重入鎖

🎄讀寫鎖

多線程之間,數據的讀取?之間不會產?線程安全問題,但數據的寫??互相之間以及和讀者之間都
需要進?互斥。如果兩種場景下都?同?個鎖,就會產?極?的性能損耗。所以讀寫鎖因此?產?。

讀寫鎖(readers-writer lock),看英?可以顧名思義,在執?加鎖操作時需要額外表明讀寫意圖,復數讀者之間并不互斥,?寫者則要求與任何?互斥。

?個線程對于數據的訪問, 主要存在兩種操作: 讀數據寫數據.

? 兩個線程都只是讀?個數據, 此時并沒有線程安全問題. 直接并發的讀取即可.
? 兩個線程都要寫?個數據, 有線程安全問題.
? ?個線程讀另外?個線程寫, 也有線程安全問題.

讀寫鎖就是把讀操作和寫操作區分對待. Java 標準庫提供了 ReentrantReadWriteLock 類, 實現
了讀寫鎖

  • ReentrantReadWriteLock.ReadLock 類表??個讀鎖. 這個對象提供了 lock / unlock ?法
    進?加鎖解鎖.
  • ReentrantReadWriteLock.WriteLock 類表??個寫鎖. 這個對象也提供了 lock / unlock
    ?法進?加鎖解鎖

其中,

  • 讀加鎖和讀加鎖之間, 不互斥.
  • 寫加鎖和寫加鎖之間, 互斥.
  • 讀加鎖和寫加鎖之間, 互斥.

注意, 只要是涉及到 “互斥”, 就會產?線程的掛起等待. ?旦線程掛起, 再次被喚醒就不知道隔了多久
了.
因此盡可能減少 “互斥” 的機會, 就是提?效率的重要途徑

讀寫鎖特別適合于 “頻繁讀, 不頻繁寫” 的場景中. (這樣的場景其實也是?常?泛存在的).

?如學校的教務系統.
每節課?師都要使?教務系統點名, 點名就需要查看班級的同學列表(讀操作). 這個操作可能要每周執
?好?次.
?什么時候修改同學列表呢(寫操作)? 就新同學加?的時候. 可能?個?都不必改?次.
再?如, 同學們使?教務系統查看作業(讀操作), ?個班級的同學很多, 讀操作?天就要進???次上
百次.
但是這?節課的作業, ?師只是布置了?次(寫操作)

Synchronized 不是讀寫鎖.、

?相關面試題

  1. 你是怎么理解樂觀鎖和悲觀鎖的,具體怎么實現呢?

悲觀鎖認為多個線程訪問同?個共享變量沖突的概率較?, 會在每次訪問共享變量之前都去真正加鎖.
樂觀鎖認為多個線程訪問同?個共享變量沖突的概率不?. 并不會真的加鎖, ?是直接嘗試訪問數據.
在訪問的同時識別當前的數據是否出現訪問沖突.
悲觀鎖的實現就是先加鎖(?如借助操作系統提供的 mutex), 獲取到鎖再操作數據. 獲取不到鎖就等待.
樂觀鎖的實現可以引??個版本號. 借助版本號識別出當前的數據訪問是否沖突. (實現細節參考上?
的圖).

2.介紹下讀寫鎖?

讀寫鎖就是把讀操作和寫操作分別進?加鎖.
讀鎖和讀鎖之間不互斥
寫鎖和寫鎖之間互斥.
寫鎖和讀鎖之間互斥.
讀寫鎖最主要?在 “頻繁讀, 不頻繁寫” 的場景中.、

3.什么是?旋鎖,為什么要使??旋鎖策略呢,缺點是什么?

如果獲取鎖失敗, ?即再嘗試獲取鎖, ?限循環, 直到獲取到鎖為?. 第?次獲取鎖失敗, 第?次的嘗試
會在極短的時間內到來. ?旦鎖被其他線程釋放, 就能第?時間獲取到鎖.
相?于掛起等待鎖,
優點: 沒有放棄 CPU 資源, ?旦鎖被釋放就能第?時間獲取到鎖, 更?效. 在鎖持有時間?較短的場景
下?常有?.
缺點: 如果鎖的持有時間較?, 就會浪費 CPU 資源.

4.synchronized 是可重?鎖么?

是可重?鎖.
可重?鎖指的就是連續兩次加鎖不會導致死鎖.
實現的?式是在鎖中記錄該鎖持有的線程?份, 以及?個計數器(記錄加鎖次數). 如果發現當前加鎖的
線程就是持有鎖的線程, 則直接計數?增.

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

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

相關文章

udp丟包問題研究

//發現udp 有收不到數據包現象. 一: 觀察丟包 1. ifconfig enp8s0 2. netstat -s -u 二: 修改系統緩存參數. recv_buffer_size 修改系統buffer_size sysctl -w net.core.rmem_max26214400 sysctl -w net.core.rmem_default26214400 三: 應用程序考慮 av_dict_set(&m_o…

cpp基礎學習筆記03:類型轉換

static_cast 靜態轉換 用于類層次結構中基類和派生類之間指針或者引用的轉換。up-casting (把派生類的指針或引用轉換成基類的指針或者引用表示)是安全的;down-casting(把基類指針或引用轉換成子類的指針或者引用)是不安全的。用于基本數據類型之間的轉換&#xff…

【C# 】進度條控件 ProgressBar 使用

進度條控件ProgressBar控件,一般作為UI界面表示某個事情進行到某個程度的外觀的體現。 那么進度條控件ProgressBar控件,在form中是怎么使用的呢? 該控件必須要用的屬性如下: private System.Windows.Forms.ProgressBar progressB…

Flutter Version Manager (FVM): Flutter的版本管理終極指南

Flutter筆記 Flutter Version Manager (FVM) - 文章信息 - Author: 李俊才 (jcLee95) Visit me at: https://jclee95.blog.csdn.netEmail: 291148484163.com. Shenzhen ChinaAddress of this article:https://blog.csdn.net/qq_28550263/article/details/136300307 my-websit…

SQL-Labs靶場“26-28”關通關教程

君衍. 一、二十六關 基于GET過濾空格以及注釋報錯注入1、源碼分析2、繞過思路3、updatexml報錯注入 二、二十六a關 基于GET過濾空格注釋字符型注入1、源碼分析2、繞過思路3、時間盲注 三、二十七關 基于union及select的過濾單引號注入1、源碼分析2、繞過思路3、聯合查詢注入4、…

laravel cache

一、基本操作 Cache::put() 創建緩存(鍵,值,有效期(單位是秒)) Cache::get() 獲取緩存 Cache::add() 只會在緩存項不存在的情況下添加數據到緩存,如果數據被成功返回 true,否則&…

Android在后臺讀取UVC攝像頭的幀數據流并推送

Android在后臺讀取UVC攝像頭的幀數據流并推送 添加UvcCamera依賴庫 使用原版的 saki4510t/UVCCamera 在預覽過程中斷開可能會閃退,這里使用的是 jiangdongguo/AndroidUSBCamera 中修改的版本,下載到本地即可。 https://github.com/jiangdongguo/AndroidU…

Rust學習筆記:基礎工具和基本名詞

不要用共享內存來通信,要用通信來共享內存 rustup: 一個用于管理 Rust 版本和相關工具的命令行工具 rustup update cargo: Rust 的構建系統和包管理工具 構建代碼下載依賴庫并構建下載庫 crate: 代碼包/庫 trait: 特性、功能 ///: 生成 html 格式的 doc&#…

CELL文獻速遞 | 了解微生物如何在社會中傳播并塑造我們的健康

谷禾健康 當人還是嬰兒時,會從父母那里得到微生物;和寵物玩耍或接觸時,也會從寵物那得到微生物;有時候人沒有直接和動物玩耍,只是接觸動物的糞便,甚至其他環境的微生物,都會交換微生物... 這些其…

智慧治水丨計訊物聯水利RTU助推小型水庫出險加固工程建設與管理

日前,水利部印發《關于健全小型水庫除險加固和運行管護機制的意見》(以下簡稱《意見》),健全小型水庫除險加固和運行管護常態化機制,提高小型水庫安全管理水平。《意見》提出了“十四五”的兩大管理機制,通…

adb下載安裝及使用教程

adb下載安裝及使用教程 一、ADB的介紹1.ADB是什么?2.內容簡介3.ADB常用命令1. ADB查看設備2. ADB安裝軟件3. ADB卸載軟件4. ADB登錄設備shell5. ADB從電腦上發送文件到設備6. ADB從設備上下載文件到電腦7. ADB顯示幫助信息 4.為什么要用ADB 二、ADB的下載1.Windows版…

Flutter GetX 之 暗黑模式

我們緊接上篇文章,今天繼續講解一下強大的 GetX 的另一個功能,就是 暗黑模式 ,在iOS 13開始蘋果的應用慢慢的都開始適配 暗黑模式,andr。oid 也慢慢的 開始跟進,截止到目前,商店的大部分應用都已經完成了 暗黑模式 的適配。 原生開發為我們提供對應的 API,那么Flutter呢…

機器學習相關概念及術語總結

目錄 1.機器學習2.監督學習3.無監督學習4.線性回歸5.邏輯回歸 1.機器學習 機器學習的定義:一個計算機程序可從經驗E(Experience)中學習如何完成任務T(Task),并且隨著經驗E的增加,性能指標P&…

Python中reduce函數和lambda表達式的學習

reduce函數將一個數據集合(鏈表,元組等)中的所有數據進行下列操作:用傳給 reduce 中的函數 function(有兩個參數)先對集合中的第 1、2 個元素進行操作,得到的結果再與第三個數據用 function 函數…

【論文精讀】DINOv2

摘要 學習與特定任務無關的預訓練表示已經成為自然語言處理的標準,這些表示不進行微調,即可在下游任務上明顯優于特定任務模型的性能。其主要得益于使用無監督語言建模目標對大量原始文本進行預訓練。 遵循NLP中的這種范式轉變,以探索計算機視…

iSlide插件2024免費版(包含52 個PPT設計輔助功能,9 大在線資源庫,以及超 50 萬 專業)

一、功能介紹 iSlide是一款專為PowerPoint設計的插件,它集合了眾多設計與效率提升的功能,幫助用戶更快速、更美觀地制作演示文稿。 主題設計:提供多種設計主題,用戶只需一鍵應用,即可為幻燈片賦予統一的視覺風格。智…

每次提出一個bug都讓測試重現,描述得那么清楚,自己操作下不會嗎?

一說到測試和開發的關系,你一定會想到一個詞“冤家”。 開發的工作就是按照PM的設計將產品最終造出來,而測試則是在開發已完成的工作里糾錯。so,測試的工作會讓開發很不爽,人之常情,誰都不喜歡自己的勞動成果被別人挑…

react路由基礎

1.目錄 A. 能夠說出React路由的作用 B. 能夠掌握react-router-dom的基本使用 C. 能夠使用編程式導航跳轉路由 D. 能夠知道React路由的匹配模式 2.目錄 A. React路由介紹 B. 路由的基本使用 C. 路由的執行過程 D. 編程式導航 E. 默認路由 F. 匹配模式 3.react路由介紹 現代…

開源項目:圖像分類技術在醫療影像分析中的應用與實踐

一、引言 在當今快速發展的醫療行業中,數字醫療正逐漸成為提升醫療服務質量和效率的關鍵力量。本項目旨在通過整合醫藥電商、遠程問診、慢病管理等多維度服務,為消費者和企業提供全面的醫療解決方案。項目的核心在于運用先進的圖像分類技術,以…

回歸測試:在不斷變化的環境中確保軟件的穩定性

軟件開發是一個復雜的過程,需要不斷變化和更新以滿足客戶不斷變化的需求,但它們也可能產生新問題或導致舊問題重新出現。這就是回歸測試的用武之地——它是在不斷變化的環境中確保軟件穩定性的重要組成部分。 在這篇文章中,我們將深入探討什…