根據同時是否允許複數的執行緒存取 critical section 可分為 exclusive 和 shared 兩類
Exclusive
指一次只能有一個 thread 進入。
lock=Monitor、Mutex、Other EventWaitHandle
Shared
一次可以有指定數量的 threads 進入。
Semaphore、ReadWriteLock
lock and Monitor
基本上 lock(){}就是
var temp = obj;
Monitor.Enter(temp);
try
{
body
}
finally
{
Monitor.Exit(temp);
}
的語法糖,如果沒有要用 Monitor.TryEnter() 設 timeout 的話都用 lock{}就可以。Mutex
以下是用作鎖的例子並附上同屬 EventWaitHandle 的 AutoResetEvent 交互參考,基本上 Mutex 的主要用途是跨 Processes 同步,沒有此需求就不要用它浪費資源了。
//static AutoResetEvent _ewh = new AutoResetEvent(true);
static Mutex _mut = new Mutex();
static bool _taken = false;
static void Main()
{
for (int i = 0; i < 5; i++)
{
Task.Run(async () =>
{
await Task.Delay(new Random().Next(100, 500));
Take();
});
}
Console.ReadLine();
}
private static void Take()
{
//_ewh.WaitOne();
_mut.WaitOne();
if (_taken)
{
Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId} attempt failed, resource was taken");
}
else
{
_taken = true;
Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId} took the resource");
}
//_ewh.Set();
_mut.ReleaseMutex();
}
Semaphore
這個跟 ReadWriteLock 都有 Slim 版,Slim 版不能跨 Processes,但資源消耗較小,一般會用 Slim 版。 用法類似 WaitHandle,但建構式處可指定進入緒的數量。
static SemaphoreSlim sphs = new SemaphoreSlim(3);
static BlockingCollection<string> resources = new BlockingCollection<string>() { "res1", "res2", "res3", "res4", "res5", "res6", "res7", "res8", "res9" };
static void Main()
{
var resCount = resources.Count;
for (int i = 0; i < resCount; i++)
{
Task.Run(async () =>
{
await Take();
});
}
Console.ReadLine();
}
private async static Task Take()
{
Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId} is waiting");
sphs.Wait();
if (resources.Any())
{
var res = resources.Take();
Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId} takes the {res}");
}
else
{
Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId} attempt failed, all resources was taken");
}
await Task.Delay(new Random().Next(500, 1000));
Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId} released");
sphs.Release();
}
我一直覺得 WaitHandle 這個家族的用法語意很差,但不知道為什麼很多類都是參考這個風格做的,搞得多緒每次寫每次查。ref: 亞斯狼(鎖差別一覽表)
沒有留言:
張貼留言