ManualResetEvent
是 C# 中的一個同步原語,它用于在多線程環境中控制對共享資源的訪問
ManualResetEvent
的工作原理如下:
初始化:創建一個 ManualResetEvent
對象時,可以選擇將其設置為初始狀態為 “signaled”(已信號)或 “non-signaled”(未信號)。如果初始狀態為 “signaled”,則一個或多個線程可以立即通過 WaitOne()
方法獲取到信號并繼續執行;如果初始狀態為 “non-signaled”,則線程必須等待直到其他線程調用 Set()
方法將其設置為 “signaled” 狀態。
等待(WaitOne):當一個線程想要訪問共享資源時,它需要調用 ManualResetEvent
對象的 WaitOne()
方法。如果當前狀態為 “non-signaled”,則該線程將被阻塞,直到其他線程調用 Set()
方法將其設置為 “signaled” 狀態。如果有多個線程在等待,只有一個線程會被喚醒并繼續執行,其他線程仍然處于阻塞狀態。
設置(Set):當一個線程完成了對共享資源的訪問并希望通知其他等待的線程時,它需要調用 ManualResetEvent
對象的 Set()
方法。這將把對象的狀態從 “non-signaled” 設置為 “signaled”,喚醒一個或多個等待的線程。
重置(Reset):有時,你可能希望將 ManualResetEvent
對象的狀態從 “signaled” 設置回 “non-signaled”,以便其他線程可以繼續等待。這可以通過調用 Reset()
方法來實現。需要注意的是,在調用 Reset()
方法之前,沒有其他線程應該調用 WaitOne()
方法,否則它們將被阻塞。
下面是一個簡單的示例,展示了如何使用 ManualResetEvent
來同步兩個線程:
using System;
using System.Threading;
class Program
{
static ManualResetEvent _event = new ManualResetEvent(false); // 初始狀態為 "non-signaled"
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 1 waiting for event...");
_event.WaitOne(); // 等待事件被設置為 "signaled"
Console.WriteLine("Thread 1 has access to the shared resource.");
Console.WriteLine("Thread 2 waiting for event...");
_event.WaitOne(); // 等待事件被設置為 "signaled"
Console.WriteLine("Thread 2 has access to the shared resource.");
}
}
在這個示例中,我們創建了兩個線程 t1
和 t2
,它們都需要訪問共享資源。我們使用一個 ManualResetEvent
對象 _event
來同步這兩個線程。當線程 t1
或 t2
訪問共享資源之前,它們會調用 WaitOne()
方法等待事件被設置為 “signaled” 狀態。當一個線程完成對共享資源的訪問后,它會調用 Set()
方法將事件設置為 “signaled” 狀態,從而通知其他等待的線程可以繼續執行。