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

Windows 8 Store Apps 多線程同步機制:Semaphore、CountdownEvent、Barrier 與事件等待

     編輯:關於.NET

前言

在多線程程式設計中,協調多個線程的執行順序與資源存取是核心課題。Windows 8 Store Apps 提供了豐富的同步原語,本文將詳細介紹 Semaphore、CountdownEvent、Barrier、ManualResetEvent 以及 AutoResetEvent 的運作原理與實際應用場景。

Semaphore / SemaphoreSlim:資源池控制

信號量 可視為「許可證中心」,限制同時存取共享資源的線程數量。SemaphoreSlim 是輕量級版本,適合單一進程內的高頻率同步。

// 建立擁有 2 個許可證的信號量
var semaphore = new SemaphoreSlim(2, 2);

for (int i = 0; i < 5; i++) {
    Task.Run(async () => {
        await semaphore.WaitAsync(); // 非阻塞等待許可證
        try {
            // 只有 2 個線程能同時進入此區塊
            await ProcessResourceAsync();
        } finally {
            semaphore.Release(); // 歸還許可證
        }
    });
}

應用場景: 連線池限流、並發檔案 I/O 控制、API 速率限制。

CountdownEvent:倒數同步

CountdownEvent 透過信號計數實現「等待 N 個操作完成」的模式。初始計數為 N,每次 Signal() 遞減,當歸零時釋放等待線程。

using (var countdown = new CountdownEvent(100)) {
    for (int i = 0; i < 100; i++) {
        Task.Run(() => {
            DoWork();
            countdown.Signal(); // 完成一項工作
        });
    }
    countdown.Wait(); // 阻塞直到 100 項全完成
}

優勢: 比手動維護計數器配合 Monitor.Wait/Pulse 更簡潔、不易出錯。

Barrier:階段式同步屏障

Barrier 適用於分階段運算的平行演算法。所有參與者呼叫 SignalAndWait() 到達屏障,最後一個到達時觸發階段結束動作(可選),然後全部釋放進入下一階段。

var barrier = new Barrier(5, b => {
    // 所有 5 個參與者到達後執行(可選的階段後動作)
    Console.WriteLine($"Phase {b.CurrentPhaseNumber} completed");
});

Parallel.For(0, 5, i => {
    Phase1Work();
    barrier.SignalAndWait(); // 等待其他參與者
    Phase2Work();
    barrier.SignalAndWait();
});

動態調整: 支援 AddParticipant/RemoveParticipant 在運行時改變參與者數量。

ManualResetEvent / ManualResetEventSlim:手動紅綠燈

「手動」意指必須顯式呼叫 Reset() 切換為紅燈(非發信狀態),Set() 切換為綠燈(發信狀態)。綠燈期間所有等待者皆可通過。

var mre = new ManualResetEventSlim(false); // 初始紅燈

// 生產者
Task.Run(() => {
    PrepareData();
    mre.Set(); // 亮綠燈,通知所有消費者
});

// 多個消費者
for (int i = 0; i < 3; i++) {
    Task.Run(() => {
        mre.Wait(); // 紅燈阻塞,綠燈通過
        ConsumeData();
    });
}
// 注意:必須手動 mre.Reset() 才會重新變紅燈

AutoResetEvent:自動紅綠燈

「自動」意指單一等待者通過 WaitOne() 後,事件會自動重置為非發信狀態(紅燈)。適合「一對一」通知模式。

var are = new AutoResetEvent(false);

Task.Run(() => {
    for (int i = 0; i < 10; i++) {
        ProduceItem(i);
        are.Set(); // 喚醒一個消費者
    }
});

Task.Run(() => {
    for (int i = 0; i < 10; i++) {
        are.WaitOne(); // 每次只有一個線程被喚醒
        ConsumeItem();
    }
});

核心差異對照表

同步原語核心語意典型用途關鍵特性
Semaphore/Slim許可證計數資源池限流計數型、支援非同步 WaitAsync
CountdownEvent倒數歸零等待 N 個任務完成一次性、不可重置
Barrier階段屏障分階段平行演算法可重用、支援動態參與者、階段後回呼
ManualResetEvent/Slim手動切換狀態廣播通知、狀態旗標需手動 Reset、多線程同步通過
AutoResetEvent自動重置單一消費者喚醒WaitOne 後自動變紅燈、一對一通知

最佳實踐建議

  • 優先使用高層抽象: Task.WhenAll、SemaphoreSlim.WaitAsync、Barrier 等現代 API,避免手工管理底層事件。
  • 避免死鎖: 取得多個鎖時保持固定順序;使用 WaitAsync 而非同步 Wait 以免阻塞 UI 線程。
  • 選擇 Slim 版本: 單一進程內同步優先用 SemaphoreSlim、ManualResetEventSlim,效能更優。
  • 釋放資源: 實作 IDisposable 的同步物件(Semaphore、CountdownEvent、Barrier)請在 using 區塊或 finally 中釋放。

熟練掌握這些同步機制,能讓你優雅地解決 Windows 8 Store Apps 中複雜的多線程協調問題。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved