首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 多執行緒機制探索(11):Mutex 互斥體進階同步、WaitAll/WaitAny/WaitOne 與 AutoResetEvent 協作模式

     編輯:關於C語言

一、Mutex:跨進程的重量級同步原語

Mutex (Mutual Exclusion) 類似「計程車」:同一時間只能有一個執行緒「搭乘」(擁有)。支援跨進程同步(具名 Mutex),功能比 lock/Monitor 強大。

二、核心方法對照

方法用途
WaitOne()等待擁有權,取得後進入關鍵區
WaitOne(timeout)帶逾時等待,避免無限阻塞
ReleaseMutex()釋放擁有權,喚醒下一個等待執行緒
WaitAll(Mutex[])等待所有 Mutex 釋放(原子性)
WaitAny(Mutex[])等待任一 Mutex 釋放

三、綜合範例:四執行緒協作同步


using System;
using System.Threading;

public class MutexSample
{
    static Mutex _m1, _m2;
    static AutoResetEvent _e1, _e2, _e3, _e4;
    const int ITERS = 100;

    public static void Main()
    {
        Console.WriteLine("Mutex Sample ...");
        _m1 = new Mutex(true, "MyMutex"); // 具名,主執行緒初始擁有
        _m2 = new Mutex(true);            // 無名,主執行緒初始擁有
        Console.WriteLine(" - Main Owns m1 and m2");

        _e1 = new AutoResetEvent(false);
        _e2 = new AutoResetEvent(false);
        _e3 = new AutoResetEvent(false);
        _e4 = new AutoResetEvent(false);
        var evs = new[] { _e1, _e2, _e3, _e4 };

        var sample = new MutexSample();
        var t1 = new Thread(sample.T1_Start); // WaitAll(m1, m2)
        var t2 = new Thread(sample.T2_Start); // WaitOne(m1)
        var t3 = new Thread(sample.T3_Start); // WaitAny(m1, m2)
        var t4 = new Thread(sample.T4_Start); // WaitOne(m2)

        t1.Start(); t2.Start(); t3.Start(); t4.Start();
        Thread.Sleep(2000);
        Console.WriteLine(" - Main releases m1");
        _m1.ReleaseMutex(); // t2, t3 條件滿足
        Thread.Sleep(1000);
        Console.WriteLine(" - Main releases m2");
        _m2.ReleaseMutex(); // t1, t4 條件滿足

        WaitHandle.WaitAll(evs); // 等待四執行緒結束
        Console.WriteLine("... Mutex Sample");
        Console.ReadLine();
    }

    public void T1_Start()
    {
        Console.WriteLine("t1 Start: WaitAll(m1, m2)");
        Mutex.WaitAll(new[] { _m1, _m2 });
        Thread.Sleep(2000);
        Console.WriteLine("t1 End: WaitAll satisfied");
        _e1.Set();
    }

    public void T2_Start()
    {
        Console.WriteLine("t2 Start: m1.WaitOne()");
        _m1.WaitOne();
        Console.WriteLine("t2 End: m1.WaitOne satisfied");
        _e2.Set();
    }

    public void T3_Start()
    {
        Console.WriteLine("t3 Start: WaitAny(m1, m2)");
        Mutex.WaitAny(new[] { _m1, _m2 });
        Console.WriteLine("t3 End: WaitAny satisfied");
        _e3.Set();
    }

    public void T4_Start()
    {
        Console.WriteLine("t4 Start: m2.WaitOne()");
        _m2.WaitOne();
        Console.WriteLine("t4 End: m2.WaitOne satisfied");
        _e4.Set();
    }
}

Mutex執行輸出

四、執行流程分析

  1. 主執行緒建立兩個 Mutex 並初始擁有(建構函式 true)
  2. 四個工作執行緒啟動,分別等待不同條件:
    • t1:WaitAll(m1, m2) → 需兩者皆釋放
    • t2:m1.WaitOne() → 需 m1 釋放
    • t3:WaitAny(m1, m2) → 需任一釋放
    • t4:m2.WaitOne() → 需 m2 釋放
  3. 主執行緒 Sleep 2 秒 → ReleaseMutex(m1) → t2、t3 解除阻塞
  4. 主執行緒 Sleep 1 秒 → ReleaseMutex(m2) → t1、t4 解除阻塞
  5. WaitHandle.WaitAll(evs) 等待四個 AutoResetEvent 全部觸發

五、AutoResetEvent:單次觸發的訊號旗標

  • Set():發送訊號,釋放單一等待執行緒,自動重置為非訊號狀態
  • WaitOne():等待訊號
  • Reset():手動重置為非訊號
  • 異於 ManualResetEvent:後者 Set() 釋放所有等待執行緒,需手動 Reset()

六、Mutex 進階特性

七、最佳實務建議

  1. 進程內同步優先用 lock/Monitor:輕量、語法簡潔、無跨進程開銷
  2. 跨進程才用具名 Mutex:單機多進程協調、單一實例應用檢查
  3. 永遠用 try/finally 保護 ReleaseMutex:避免異常導致永久阻塞
  4. 避免 WaitAll 大量 Mutex:STA 執行緒限制、效能較差
  5. 考慮 SemaphoreSlim/AsyncLock:非同步等待支援

總結

Mutex 提供跨進程、具名、原子 WaitAll/WaitAny的重量級同步能力。配合 AutoResetEvent 追蹤執行緒完成狀態,可構建複雜的多執行緒協作流程。但進程內同步請優先選擇 lock、SemaphoreSlim、ReaderWriterLockSlim 等輕量替代方案。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
特性說明
跨進程同步具名 Mutex 系統級可見,不同進程可共享
擁有權語意只有擁有者能 ReleaseMutex,否則擲例外
遺棄 Mutex擁有者異常終止未釋放,下一個等待者取得並收到 AbandonedMutexException
重進入同一執行緒可多次 WaitOne,需對應次數 ReleaseMutex