網頁

2015年11月24日 星期二

C# Thread Monitor 鎖定作業

Last Update: 2015/11/24 18:55+08



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();
}

沒有留言:

張貼留言