根據同時是否允許複數的執行緒存取 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: 亞斯狼(鎖差別一覽表)
沒有留言:
張貼留言