Intro
C# 執行緒同步or鎖定作業的方式System.Threading.Monitor這邊稱為鎖定並不是keyword, 只是相較等候的方式, 這裡的行為比較像鎖定
另一種方法是等候作業 C# Thread 等候其它作業
Content
一般用法, 鎖定一個物件, 避免搶資源, 與 lock(obj)相同? 以下程式表示, 同時間, 只有一個thread可以在Enter與Exit之間
static void Main(string[] args)
{
object obj = new Object();
var thd1 = new Thread(delegate()
{
Console.WriteLine("Start thd1");
try
{
Monitor.Enter(obj);
Console.WriteLine("enter thd1"); Thread.Sleep(1000);
}
finally { Monitor.Exit(obj); Console.WriteLine("thd1 exit"); }
Console.WriteLine("End thd1");
});
var thd2 = new Thread(delegate()
{
Console.WriteLine("Start thd2");
try
{
Monitor.Enter(obj);
Console.WriteLine("enter thd2"); Thread.Sleep(1000);
}
finally { Monitor.Exit(obj); Console.WriteLine("thd2 exit"); }
Console.WriteLine("End thd2");
});
thd1.Start();
thd2.Start();
Console.ReadKey();
}
用法2: 暫時讓出鎖定物件, 用等待(wait)和喚醒(pulse)的方式
static void Main(string[] args)
{
object obj = new Object();
var thd1 = new Thread(delegate()
{
Console.WriteLine("thd1 Start");
lock (obj) //step2. thd1 勢必先取得 obj-lock
{
Monitor.Wait(obj); // step3. 但它把obj-lock讓出去, 並進入wait-staus
Console.WriteLine("thd1 1st");
Monitor.Pulse(obj); // step7. 叫醒等待中的thd2
Monitor.Wait(obj); // step8. 把obj-lock讓出去, 並進入 wait-staus
Console.WriteLine("thd1 2nd");
Monitor.Pulse(obj); // step11. 叫醒等待中的thd2
Monitor.Wait(obj); // step12. 把obj-lock讓出去, 並進入 wait-staus
Console.WriteLine("thd1 3rd");
Monitor.Pulse(obj); // step14. 叫醒等待中的thread
}
Console.WriteLine("thd1 End");
});
var thd2 = new Thread(delegate()
{
Console.WriteLine("thd2 Start");
Thread.Sleep(1000); //step1. 讓thd2比較慢進入lock處理
lock (obj) // step4. thd2 取得 thd1 第一次讓出的obj-lock
{
Console.WriteLine("thd2 1st");
Monitor.Pulse(obj); // step5. 進入等待前把其它thread(thd1)叫起來, 通知它們進入runing狀態
//這邊註解的話有可能造成死鎖, 因為 thd1 進入 wait-staus, 而 thd2 在下一行即將進入wait-staus
//在thd1下次取消執行權時就會往下跑
Monitor.Wait(obj); //step6. 把obj-lock讓出去, 並進入 wait-staus
Console.WriteLine("thd2 2nd");
Monitor.Pulse(obj); // step9. 叫醒等待中的thd1
Monitor.Wait(obj); // step10. 把obj-lock讓出去, 並進入 wait-staus
Console.WriteLine("thd2 3rd");
Monitor.Pulse(obj); // step13. 叫醒等待中的thd1
}
Console.WriteLine("thd2 End");
});
thd1.Start();
thd2.Start();
Console.ReadKey();
}
沒有留言:
張貼留言