1:Mutex
Mutex 就像一個C# lock一樣,不同的是它可以跨程序.
進入和釋放一個Mutex要花費幾毫秒,大約比C#的lock慢50倍。
使用一個Mutex的執行個體,調用WaitOne方法來擷取鎖,ReleaseMutex方法來釋放鎖。
因為Mutex是跨程序的,是以我們可以使用Mutex來檢測程式是否已經運作。
<a></a>
public static void MainThread()
{
using (var mutex = new Mutex(false, "LoveJenny OneAtATimeDemo"))
{
if (!mutex.WaitOne(TimeSpan.FromSeconds(3), false))
{
Console.WriteLine("隻能運作一個應用程式!");
return;
}
RunProgram();
}
}
2:Semaphore:
一個Semaphore就像一個酒吧一樣,通過門衛來限制它的客人,一旦到達限制,沒有人可以進入,
人們會在門外乖乖的排隊,一旦有一個人離開酒吧,排隊中的人就可以進入了一個了。
下面是個例子:
class TheClub
{
//隻能容納三個人的酒吧
static SemaphoreSlim _sem = new SemaphoreSlim(3);
public static void MainThread()
for (int i = 1; i <= 5; i++)
new Thread(Enter).Start(i); //有5個人向進入
static void Enter(object id)
Console.WriteLine(id + " 想要進入了");
_sem.Wait();
Console.WriteLine(id+" 已經進入了!");
Thread.Sleep(1000 * (int)id);
Console.WriteLine(id + " 離開了?");
_sem.Release();
}
3:AutoResetEvent
一個AutoResetEvent就像十字轉門一樣,插入一張票就讓一個人通過,”Auto”代表門會自動的關上。
在十字門外面的人可以調用WaitOne方法來阻塞,等待。一旦有人插入了票(調用Set方法),就可以讓外面等待的人(調用WaitOne方法的線程)通過了。
建立AutoResetEvent有一個參數。
static EventWaitHandle _waitHandle = new AutoResetEvent(false);
其中false在msdn的解釋是:初始狀态為非終止,
按照我個人的了解false代表了十字轉門非終止,是以可以正常的進入,等待。
而如果是true的話:初始狀态為終止,也就是代表已經調用了Set了,
就是說十字轉門已經停止了,是以接下來如果有人調用了WaitOne方法,這個調用WaitOne方法的人直接就可以進入了,不需要再插入票(不需要調用Set)了,之後的調用和false一緻,這一點可以認為AutoResetEvent具有記憶功能,它記住了上次門是打開的狀态。是以調用waitone方法可以進入。
class ThreadAutoResetEvent
static EventWaitHandle _waitHandle = new AutoResetEvent(false);
new Thread(Waiter).Start();
Thread.Sleep(2000);
_waitHandle.Set();
static void Waiter()
Console.WriteLine("Waiting...");
_waitHandle.WaitOne();
Console.WriteLine("Notified");
}
很簡單,Waiter執行到Waiting…後,就開始調用WaitOne了,是以在門外排隊等待。
而主線程在睡了兩秒後,開始插入一張票(Set).是以Waiter就繼續執行,是以列印Notified
接下來我們使用AutoResetEvent來模拟實作生産消費問題:
class ProducerConsumerQueue:IDisposable
EventWaitHandle _wh = new AutoResetEvent(false);
Thread _worker;
readonly object _locker = new object();
Queue<string> _tasks = new Queue<string>();
public ProducerConsumerQueue()
//建立并啟動工作線程
_worker = new Thread(Work);
_worker.Start();
public void EnqueueTask(string task)
lock (_locker) _tasks.Enqueue(task);
_wh.Set(); //一旦有任務了,喚醒等待的線程
public void Dispose()
EnqueueTask(null);
_worker.Join(); //等待_worker線程執行結束
_wh.Close();
void Work()
while (true)
string task = null;
lock (_locker)
if (_tasks.Count > 0)
{
task = _tasks.Dequeue();
if (task == null)
return;
}
if (task != null) //如果有任務的話,執行任務
Console.WriteLine("Performing task: " + task);
Thread.Sleep(1000);
else //否則阻塞,去睡覺吧
_wh.WaitOne();
主線程調用如下:
public static void Main()
using (ProducerConsumerQueue q = new ProducerConsumerQueue())
q.EnqueueTask("Hello");
for (int i = 0; i < 10; i++) q.EnqueueTask("Say " + i);
q.EnqueueTask("Goodbye!");
4:ManualResetEvent:
一個ManualResetEvent就是一個普通門,
調用Set方法門就打開了,允許任意數量的人進入。
調用WaitOne方法就開始等待進入。
調用Reset方法門就關閉了。
在一個關閉的門上調用WaitOne方法就會被阻塞。
當門下次被打開的時候,所有等待的線程都可以進入了。
除了這些不同外,一個ManualResetEvent和AutoResetEvent類似。
在Framework4.0中ManualResetEvent提供了一個優化版本。ManualResetEventSlim。後面的版本速度更快,并且支援取消(CancellationToken).
本文轉自LoveJenny部落格園部落格,原文連結:http://www.cnblogs.com/LoveJenny/archive/2011/05/24/2053677.html,如需轉載請自行聯系原作者