怎麼正確使用鎖?

来源:https://www.cnblogs.com/wing011203/archive/2023/03/18/17229582.html
-Advertisement-
Play Games

這篇文章主要關註分散式鎖,包括加鎖和解鎖的過程,鎖的用法,加鎖帶來的代價,對性能的影響以及如何避免死鎖。 ...


鎖的原理:任何時間都只能有一個線程持有鎖,只有持有鎖的線程才能訪問被鎖保護的資源。

我們接下來看一下在鎖的使用上有什麼最佳實踐。

避免濫用鎖

如果能不用鎖,就不用鎖;如果你不確定是不是應該用鎖,那也不要鎖。

使用鎖後帶來的代價:

  1. 加鎖和解鎖過程都需要CPU時間的,這是一個性能的損失。使用鎖還可能導致線程等待鎖,等待鎖過程中的線程是阻塞狀態,過多的鎖等待會顯著降低程式的性能。
  2. 如果對鎖使用不當,很容易造成死鎖,導致整個程式“卡死”,這是非常嚴重的問題。

我們不可以看到一個共用數據,在沒有搞清楚它在併發環境中是否會出現爭用問題,就“為了保險,給它加個鎖吧。”,千萬不要有這種不負責任的想法,否則你將會付出慘痛的代價。

只有在併發環境中,共用資源不支持併發訪問,或者說併發訪問共用資源會導致系統錯誤的情況下,才需要使用鎖。

鎖的用法

使用鎖的過程可以分為三步:

  1. 在訪問共用資源之前,先獲取鎖。
  2. 如果獲取鎖成功,就可以訪問共用資源了。
  3. 使用完共用資源後釋放鎖,以便其他線程繼續訪問共用資源。

我們在使用鎖的過程中,需要註意使用完鎖,一定要釋放它。我們需要考慮到代碼可能走到的所有正常和異常的分支,確保所有情況下,鎖都能被釋放。

死鎖

死鎖是指由於某種原因,鎖一直沒有釋放,後續需要獲取鎖的線程都將處於等解鎖狀態。

大部分編程語言都提供了可重入鎖,如果沒有特別的需求,我們也要儘量使用可重入鎖。

下麵是幾條如何避免死鎖的建議:

  1. 避免濫用鎖。
  2. 對於同一把鎖,加鎖和解鎖必須要放在同一個方法中,這樣一次加鎖對應一次解鎖,代碼清晰簡單,便於分析問題。
  3. 儘量避免在持有一把鎖的情況下,去獲取另外一把鎖,就是要儘量避免同時持有多把鎖。
  4. 如果需要持有多把鎖,一定要註意加解鎖的順序,解鎖的順序要和加鎖的殊勛想法,比如,獲取三把鎖的順序是A、B、C,釋放鎖的順序必須是C、B、A。

使用讀寫鎖兼顧性能和安全

對於共用數據,如果我們的方法只是去讀取它,而不會修改,也是需要加鎖的,因為有可能在讀取數據的過程中,有其他線程會更新數據。

但如果只是簡單地為數據加一個鎖,對於“讀多寫少”的場景,性能會受到影響。針對數據的讀寫操作,我們希望能夠做到:1)讀操作可以併發執行,2)寫的同時不能併發讀,也不能併發寫。

Java中的ReadWriteLock可以用來解決這個問題,看下麵的代碼框架:


ReadWriteLock rwlock = new ReentrantReadWriteLock();

public void read() {
  rwlock.readLock().lock();
  try {
    // 在這兒讀取共用數據
  } finally {
    rwlock.readLock().unlock();
  }
}
public void write() {
  rwlock.writeLock().lock();
  try {
    // 在這兒更新共用數據
  } finally {
    rwlock.writeLock().unlock();
  }
}

在這段代碼中,需要讀數據的時候,我們獲取鎖,這個鎖不是一個互斥鎖,即read()方法可以支持多個線程並行執行,從而保證數據的讀性能。寫數據的時候,我們獲得寫鎖,這是一個互斥鎖,當一個線程持有寫鎖的時候,其他線程既無法獲得讀鎖,也無法獲得寫鎖,從而達到了保護數據的目的。

    作者:李潘     出處:http://wing011203.cnblogs.com/     本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 前騰訊工程師,經歷過大廠,也經歷過創業! 我已奔四,但我還在持續學習,持續成長! 我非常樂意把我的經驗和心得分享給你! 我是阿銘,關註我,和我一起成長為技術大牛! ↓↓↓↓↓ 關於DevOps這個概念,可能100個人能給出100個說法,這是因為每個人所接觸到的環境有所差異,不同的公司要解決的問題自然 ...
  • 案例現象 這天,監控系統發來一條告警消息,內容說某台伺服器根目錄磁碟占用空間達到閾值,超過百分之八十了 登上伺服器,df -Th 看一下,發現磁碟空間確實不夠用了 進入到根目錄,然後 du -sh * 可以看到,var 目錄下的磁碟空間已經占用了 75G 既然如此,刪除 var 目錄下一些占空間較大 ...
  • reactive reactive 創建一個深層的對象的響應式代理,即對象根屬性以及嵌套對象的屬性都是響應式的。如果使用 ES6 結構賦值,就會使得這個對象的響應式代理第一層(根屬性)屬性失去響應式,但其嵌套下的對象屬性還是響應式的。 shallowReactive 會創建淺層的對象的響應式代理,只 ...
  • 1 前言 最近有個需求,需要使用JS快速讀取外部大數據文件(60w條記錄的表)。筆者嘗試過使用JS讀取Excel文件,但是跑了十幾分鐘仍未出結果,後來筆者嘗試將原數據保存為TXT文件,再從TXT文件中讀取數據,只需幾秒鐘即可讀取完畢。在此分享一下,也留著以後備用。 2 案例 為方便快速理解,筆者挑選 ...
  • 前端常見的十種佈局方式 作為一個開發小白,也是第一次編寫博客文章,若有錯誤請各位大牛大佬指正,輕噴!!! 我在學校接觸最多的就是前端,然後最近在學習新的前端知識,發現前端佈局常見的有很多種,不同的應用場景有不同的佈局方式,下麵就來簡單介紹一下吧。 靜態佈局 浮動佈局 定位佈局 柵格佈局 table布 ...
  • 此內容包含: html基礎 列表、表格 媒體元素 表單(重點) 1、HTML 基礎 目標: 會使用HTML5的基本結構創建網頁 會使用文本相關標簽排版文本信息 會使用圖像相關標簽實現圖文並茂的頁面 會使用標簽創建超鏈接、錨鏈接及功能性鏈接 1.1、什麼是HTML HTML:Hyper Text Ma ...
  • 定義 如果希望動態給某個類添加一些屬性或者方法,但是你又不希望這個類派生的對象受到影響,那麼裝飾器模式就可以給你帶來這樣的體驗。 它的定義就是在不改變原對象的基礎上,通過對其進行包裝拓展,使得原有對象可以動態具有更多功能,從而滿足用戶的更複雜需求。 舉個例子,一部手機,你可以買各種花里胡哨的手機殼等 ...
  • MVVM M:模型(Model):data V:視圖(View):模板 VM:視圖模型(ViewModel):Vue實例對象 Vue收到了MVVM模型的啟發,MVVM是vue實現數據驅動視圖和雙向數據綁定的核心原理,通過ViewModel監聽DOM和數據源的變化。 Object.defineProp ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...