聊透多線程編程-線程互斥與同步-13. C# Mutex類實現線程互斥

目錄

一、什么是臨界區?

二、Mutex類簡介

三、Mutex的基本用法

解釋:

四、Mutex的工作原理

五、使用示例1-保護共享資源

解釋:

六、使用示例2-跨進程同步

示例場景

1. 進程A - 主進程

2. 進程B - 第二個進程

輸出結果

ProcessA 的輸出

ProcessB 的輸出

解釋

七、注意事項

八、總結


?

在多線程編程中,線程之間的同步和互斥是確保程序正確運行的重要機制。C# 提供了多種工具來實現線程同步,其中 Mutex 是一種功能強大的同步原語,特別適合用于跨進程的線程互斥場景。本文將詳細介紹如何使用 Mutex 類實現線程互斥,并通過示例展示其工作原理。


一、什么是臨界區?

在多線程編程中,臨界區是指一段需要互斥訪問的代碼塊,通常涉及對共享資源的操作。為了避免多個線程同時操作共享資源而導致數據競爭或狀態不一致,我們需要對臨界區代碼進行保護。

例如,如果兩個線程同時修改一個共享變量,可能會導致最終結果不符合預期。因此,我們需要一種機制來確保同一時間只有一個線程可以進入臨界區。


二、Mutex類簡介

Mutex(Mutual Exclusion)類是 .NET 提供的一種線程同步工具,用于實現線程間的互斥訪問。與 lockMonitor 不同,Mutex 支持跨進程的線程同步,這使得它非常適合用于多進程環境下的資源保護。

Mutex 的主要特點包括:

  • 跨進程支持Mutex?可以在不同進程之間共享,適用于分布式或多進程應用。
  • 獨占鎖:同一時間只有一個線程(或進程)可以持有?Mutex
  • 命名支持:可以通過命名方式創建全局?Mutex,從而實現跨進程同步。

三、Mutex的基本用法

Mutex 的基本用法包括以下幾個步驟:

  1. 創建?Mutex?對象。
  2. 調用?WaitOne?方法獲取鎖。
  3. 執行需要同步的代碼塊。
  4. 調用?ReleaseMutex?方法釋放鎖。

為了確保資源的正確釋放,通常會將 Mutex 放入 using 塊中,這樣即使發生異常,也能保證資源被正確釋放。

using System;
using System.Threading;class Program
{private static readonly Mutex _mutex = new Mutex(); // 創建 Mutex 對象static void Main(){Thread t1 = new Thread(DoWork);Thread t2 = new Thread(DoWork);t1.Start();t2.Start();t1.Join();t2.Join();}static void DoWork(){Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId}: Waiting for mutex...");_mutex.WaitOne(); // 獲取鎖try{Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId}: Entered critical section.");Thread.Sleep(2000); // 模擬一些工作}finally{_mutex.ReleaseMutex(); // 釋放鎖Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId}: Released mutex.");}}
}

解釋:

  • _mutex.WaitOne():嘗試獲取鎖。如果鎖已被占用,則當前線程會被阻塞,直到鎖可用。
  • _mutex.ReleaseMutex():釋放鎖,允許其他線程獲取該鎖。
  • 使用?try-finally?塊是為了確保即使發生異常,鎖也能被正確釋放。

四、Mutex的工作原理

Mutex 的核心思想是基于操作系統級別的信號量機制,提供了更高級別的同步能力:

  1. 當線程調用?WaitOne?方法時,它會嘗試獲取?Mutex。如果?Mutex?已被其他線程占用,則當前線程會被掛起,直到?Mutex?可用。
  2. 當線程調用?ReleaseMutex?方法時,它會釋放?Mutex,允許其他線程獲取該鎖。
  3. 如果?Mutex?是命名的(通過構造函數指定名稱),它可以跨進程共享,從而實現跨進程同步。

五、使用示例1-保護共享資源

下面是一個使用 Mutex 類保護共享資源的例子:

using System;
using System.Threading;class Program
{private static int _counter = 0;private static readonly Mutex _mutex = new Mutex();static void Main(){Thread t1 = new Thread(IncrementCounter);Thread t2 = new Thread(IncrementCounter);t1.Start();t2.Start();t1.Join();t2.Join();_mutex.Dispose();Console.WriteLine($"Final Counter Value: {_counter}");}static void IncrementCounter(){for (int i = 0; i < 100000; i++){_mutex.WaitOne();try{_counter++;}finally{_mutex.ReleaseMutex();}}}
}

解釋:

  • _mutex?是一個靜態對象,用于標識鎖。
  • 每次訪問?_counter?時,都會通過?WaitOne?獲取鎖,并通過?ReleaseMutex?釋放鎖。
  • 最終輸出的結果是?200000,因為所有線程的操作都被正確同步了。

六、使用示例2-跨進程同步

Mutex 的跨進程同步能力使其非常適合用于分布式或多進程環境中的資源共享和互斥訪問。下面通過一個完整的例子,演示如何使用命名的 Mutex 來實現跨進程同步。

示例場景

假設我們有兩個獨立的應用程序(進程),它們都需要訪問一個共享資源(例如文件或數據庫)。為了避免數據競爭,我們需要確保同一時間只有一個進程可以訪問該資源。我們將使用命名的 Mutex 來實現這一目標。

1. 進程A - 主進程

這是第一個應用程序,它嘗試獲取 Mutex 并獨占訪問共享資源。

// ProcessA.cs
using System;
using System.Threading;class Program
{static void Main(string[] args){// 創建一個命名的 Mutexbool isCreatedNew; // 是否是第一個創建 Mutex 的進程using (Mutex mutex = new Mutex(true, "Global\\SharedResourceMutex", out isCreatedNew)){if (isCreatedNew){Console.WriteLine("Process A: This process owns the mutex.");Console.WriteLine("Process A: Accessing shared resource...");// 模擬對共享資源的操作Thread.Sleep(50000); // 假設操作需要 5 秒                Console.WriteLine("Process A: Releasing mutex.");//釋放鎖mutex.ReleaseMutex();}else{Console.WriteLine("Process A: Another process already owns the mutex. Waiting...");// 等待其他進程釋放 Mutexmutex.WaitOne();Console.WriteLine("Process A: Acquired mutex after waiting.");// 模擬對共享資源的操作Console.WriteLine("Process A: Accessing shared resource...");Thread.Sleep(5000);Console.WriteLine("Process A: Releasing mutex.");//釋放鎖mutex.ReleaseMutex();}}}
}

2. 進程B - 第二個進程

這是第二個應用程序,它也會嘗試獲取同一個 Mutex,并訪問共享資源。

// ProcessB.cs
using System;
using System.Threading;class Program
{static void Main(string[] args){// 創建一個命名的 Mutexbool isCreatedNew; // 是否是第一個創建 Mutex 的進程using (Mutex mutex = new Mutex(true, "Global\\SharedResourceMutex", out isCreatedNew)){try{if (isCreatedNew){Console.WriteLine("Process B: This process owns the mutex.");Console.WriteLine("Process B: Accessing shared resource...");// 模擬對共享資源的操作Thread.Sleep(5000); // 假設操作需要 5 秒Console.WriteLine("Process B: Releasing mutex.");//釋放鎖mutex.ReleaseMutex();}else{Console.WriteLine("Process B: Another process already owns the mutex. Waiting...");// 等待其他進程釋放 Mutexmutex.WaitOne();Console.WriteLine("Process B: Acquired mutex after waiting.");// 模擬對共享資源的操作Console.WriteLine("Process B: Accessing shared resource...");Thread.Sleep(5000);Console.WriteLine("Process B: Releasing mutex.");//釋放鎖mutex.ReleaseMutex();}}catch (AbandonedMutexException){Console.WriteLine("Process B: Detected an abandoned mutex. Continuing execution...");// 即使檢測到被遺棄的 Mutex,當前線程仍然可以繼續執行。}}}
}

輸出結果

ProcessA 的輸出

Process A: This process owns the mutex.
Process A: Accessing shared resource...
Process A: Releasing mutex.

ProcessB 的輸出

Process B: Another process already owns the mutex. Waiting...
Process B: Acquired mutex after waiting.
Process B: Accessing shared resource...
Process B: Releasing mutex.

解釋

  1. 命名的 Mutex

    • 在?new Mutex(true, "Global\\SharedResourceMutex", out isCreatedNew)?中,"Global\\SharedResourceMutex"?是?Mutex?的名稱。
    • Global\\?前綴表示該?Mutex?是全局的,可以在不同進程之間共享。
  2. 跨進程同步

    • 當?ProcessA?創建?Mutex?時,isCreatedNew?為?true,表示它是第一個創建該?Mutex?的進程。
    • 當?ProcessB?嘗試創建同名的?Mutex?時,isCreatedNew?為?false,表示該?Mutex?已存在,并由另一個進程持有。
  3. 等待與釋放

    • 如果?Mutex?已被占用,調用?mutex.WaitOne()?會使當前線程阻塞,直到?Mutex?被釋放。
    • 調用?mutex.ReleaseMutex()?會釋放?Mutex,允許其他線程或進程獲取它。

七、注意事項

  1. 命名沖突

    • 命名的?Mutex?必須具有唯一性,避免與其他應用程序發生沖突。
    • 可以使用 GUID 或特定的前綴來確保名稱的唯一性。
  2. 性能開銷

    • Mutex?是基于操作系統級別的同步機制,性能開銷較大,尤其是在高并發場景下。
    • 對于單進程內的線程同步,推薦使用?lock?或?Monitor
  3. 死鎖風險

    • 如果一個進程獲取了?Mutex?但未釋放,會導致其他進程永遠無法獲取鎖。
    • 確保在?finally?塊中調用?ReleaseMutex,避免因異常導致鎖未釋放。
  4. 權限問題

    • 在某些情況下,創建全局?Mutex?可能需要管理員權限,尤其是在 Windows 系統中。
  5. 為什么使用 using

    • 將?Mutex?放入?using?塊中可以確保資源的正確釋放,避免資源泄漏。
    • 即使發生異常,Dispose?方法也會被自動調用,保證資源管理的安全性和可靠性。

八、總結

Mutex 類是 C# 中實現線程互斥的一種重要工具,特別適合用于跨進程的線程同步場景。盡管它的使用稍微復雜一些,但能夠滿足更多高級需求,例如分布式系統中的資源保護。

在實際開發中,選擇合適的同步機制非常重要。對于簡單的線程互斥場景,lockMonitor 可能更為直觀;而對于需要跨進程同步的場景,Mutex 則是一個不錯的選擇。通過合理利用 Mutex,我們可以有效避免數據競爭和資源沖突,確保多線程或多進程應用的穩定性和可靠性。

?

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

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

相關文章

stm32week12

stm32學習 九.stm32與HAL庫 2.HAL庫框架 總架構&#xff1a; 文件介紹&#xff1a; ppp是某一外設&#xff0c;ex是拓展功能 HAL庫API函數和變量命名規則&#xff1a; HAL庫對寄存器位操作的相關宏定義&#xff1a; HAL庫的回調函數&#xff1a; 3.STM32啟動過程 MDK編譯過…

opencv HSV的具體描述

色調H&#xff1a; 使用角度度量&#xff0c;取值范圍為0\~360&#xff0c;從紅色開始按逆時針方向計算&#xff0c;紅色為0&#xff0c;綠色為120&#xff0c;藍色為240。它們的補色是&#xff1a;黃色為60&#xff0c;青色為180&#xff0c;紫色為300。通過改變H的值&#x…

Java Lambda表達式指南

一、Lambda表達式基礎 1. 什么是Lambda表達式&#xff1f; 匿名函數&#xff1a;沒有名稱的函數函數式編程&#xff1a;可作為參數傳遞的代碼塊簡潔語法&#xff1a;替代匿名內部類的更緊湊寫法 2. 基本語法 (parameters) -> expression 或 (parameters) -> { statem…

面向對象設計中的類的分類:實體類、控制類和邊界類

目錄 前言1. 實體類&#xff08;Entity Class&#xff09;1.1 定義和作用1.2 實體類的特點1.3 實體類的示例 2. 控制類&#xff08;Control Class&#xff09;2.1 定義和作用2.2 控制類的特點2.3 控制類的示例 3. 邊界類&#xff08;Boundary Class&#xff09;3.1 定義和作用3…

C# 封裝教程

原文&#xff1a;C# 封裝_w3cschool &#xff08;注&#xff1a;本文為教程文章&#xff0c;請勿標記為付費文章&#xff01;特此聲明&#xff09; 封裝 被定義為"把一個或多個項目封閉在一個物理的或者邏輯的包中"。在面向對象程序設計方法論中&#xff0c;封裝是…

量化交易 - RSRS(阻力支撐相對強度)- 正確用法 - 年均收益18%

經過研究&#xff0c;發現RSRS的正確用法其實是需要用到兩個數據&#xff0c;分別是 n: 一階擬合樣本數&#xff0c;m:求均值方差樣本數&#xff0c;其中n比較小 如18&#xff0c;m比較大 如1100 經過調優后&#xff0c;收益率顯著上升&#xff01; 如下圖&#xff1a; &…

Oracle expdp的 EXCLUDE 參數詳解

Oracle expdp的 EXCLUDE 參數詳解 EXCLUDE 是 Oracle Data Pump Export (expdp) 工具中的一個關鍵參數&#xff0c;用于指定在導出過程中要排除的對象或對象類型。 一、基本語法 expdp username/password DUMPFILEexport.dmp DIRECTORYdpump_dir EXCLUDEobject_type[:name_c…

如何使用3DMAX插件PFSpliner將3D對象轉化為藝術樣條線?

什么是粒子流源(Particle Flow)是3DMAX的一個功能極其強大的粒子系統。它采用事件驅動模型,使用一個名為“粒子視圖”的特殊對話框。在“粒子視圖”中,您可以將描述粒子屬性(如形狀、速度、方向和一段時間內的旋轉)的單個運算符組合成稱為事件的組。每個操作符都提供一組…

【python】 循環語句(while)

1、循環語句 語法&#xff1a; while 條件:......... #只有條件為真時&#xff0c;才會執行while中的內容。 1.1循環語句基本使用 示例1&#xff1a; print("開始") while 1>2:print("人生得意須盡歡") print("結束") #輸出結果&#…

OOA-CNN-LSTM-Attention、CNN-LSTM-Attention、OOA-CNN-LSTM、CNN-LSTM四模型多變量時序預測一鍵對比

OOA-CNN-LSTM-Attention、CNN-LSTM-Attention、OOA-CNN-LSTM、CNN-LSTM四模型多變量時序預測一鍵對比 目錄 OOA-CNN-LSTM-Attention、CNN-LSTM-Attention、OOA-CNN-LSTM、CNN-LSTM四模型多變量時序預測一鍵對比預測效果基本介紹程序設計參考資料 預測效果 基本介紹 基于OOA-CN…

20250421在榮品的PRO-RK3566開發板的Android13下頻繁重啟RKNPU fde40000.npu: Adding to iommu gr

20250421在榮品的PRO-RK3566開發板的Android13下頻繁重啟RKNPU fde40000.npu: Adding to iommu gr 2025/4/21 14:50 緣起&#xff1a;電池沒電了&#xff0c;導致榮品的PRO-RK3566的核心板頻繁重啟。 內核時間4s就重啟。100%復現。 PRO-RK3566 Android13啟動到這里 復位&#…

動態監控進程

1.介紹: top和ps命令很相似,它們都是用來顯示正在執行的進程,top和ps最大的不同之處,在于top在執行中可以更新正在執行的進程. 2.基本語法&#xff1a; top [選項] 選項說明 ??僵死進程&#xff1a;內存沒有釋放,但是進程已經停止工作了,需要及時清理 交互操作說明 應用案…

657SJBH西藏藏藥特產銷售管理系統

畢業論文&#xff08;設計&#xff09;文獻綜述 西藏藏藥特產銷售管理系統的設計與實現 近年來&#xff0c;隨著網絡技術特別是Internet技術的普及和發展&#xff0c;電子商務的開發和應用成為一個熱門領域&#xff0c;在線藏藥特產銷售系統就是這其中的一員。 藏藥產業在西藏…

棧和隊列--數據結構初階(2)(C/C++)

文章目錄 前言理論部分棧的模擬實現STL中的棧容器隊列的模擬實現STL中的隊列容器 作業部分 前言 這期的話會給大家講解棧和隊列的模擬實現和在STL中棧和隊列怎么用的一些知識和習題部分(這部分側重于理論知識&#xff0c;習題倒還是不難) 理論部分 棧的模擬實現 typedef int…

RNN的理解

對于RNN的理解 import torch import torch.nn as nn import torch.nn.functional as F# 手動實現一個簡單的RNN class RNN(nn.Module):def __init__(self, input_size, hidden_size, output_size):super(RNN, self).__init__()# 定義權重矩陣和偏置項self.hidden_size hidden…

二叉查找樹和B樹

二叉查找樹&#xff08;Binary Search Tree, BST&#xff09;和 B 樹&#xff08;B-tree&#xff09;都是用于組織和管理數據的數據結構&#xff0c;但它們在結構、應用場景和性能方面有顯著區別。 二叉查找樹&#xff08;Binary Search Tree, BST&#xff09; 特點&#xff1…

一段式端到端自動駕駛:VAD:Vectorized Scene Representation for Efficient Autonomous Driving

論文地址&#xff1a;https://github.com/hustvl/VAD 代碼地址&#xff1a;https://arxiv.org/pdf/2303.12077 1. 摘要 自動駕駛需要對周圍環境進行全面理解&#xff0c;以實現可靠的軌跡規劃。以往的方法依賴于密集的柵格化場景表示&#xff08;如&#xff1a;占據圖、語義…

OpenCV訓練題

一、創建一個 PyQt 應用程序&#xff0c;該應用程序能夠&#xff1a; 使用 OpenCV 加載一張圖像。在 PyQt 的窗口中顯示這張圖像。提供四個按鈕&#xff08;QPushButton&#xff09;&#xff1a; 一個用于將圖像轉換為灰度圖一個用于將圖像恢復為原始彩色圖一個用于將圖像進行…

opencv函數展示4

一、形態學操作函數 1.基本形態學操作 &#xff08;1&#xff09;cv2.getStructuringElement() &#xff08;2&#xff09;cv2.erode() &#xff08;3&#xff09;cv2.dilate() 2.高級形態學操作 &#xff08;1&#xff09;cv2.morphologyEx() 二、直方圖處理函數 1.直方圖…

iPhone 13P 換超容電池,一年實記的“電池循環次數-容量“柱狀圖

繼上一篇 iPhone 13P 更換"移植電芯"和"超容電池"&#x1f50b;體驗&#xff0c;詳細記錄了如何更換這兩種電池&#xff0c;以及各自的優略勢對比。 一晃一年過去&#xff0c;時間真快&#xff0c;這次分享下記錄了使用超容電池的 “循環次數 - 容量(mAh)…