2011-05-04 105 views
4

這個例子有什麼問題,它在Monitor.PulaseAll(yyy)上拋出錯誤「對象同步方法是從一個非同步的代碼塊中調用的?這裏Monitor.PulaseAll拋出錯誤

class Program 
{ 
    static object yyy = 1; 

    public static void test(int x) 
    { 

     while (true) 
     { 
      lock (yyy) 
      { 
       Console.WriteLine("T" + x.ToString()); 
       while (x != (int)yyy) 
       { 
        Monitor.Wait(yyy); 
        continue; 
       } 

       Console.Write(new string(x.ToString()[0], 20)); 

       yyy = 1 + (int)yyy; 
       yyy = ((int)yyy == 4) ? 1 : yyy; 

       Console.WriteLine("------------------------1--"); 
       Monitor.PulseAll(yyy); 
       Console.WriteLine("------------------------2--"); 
      } 
     } 
    } 

    public static void Main() 
    { 
     Thread t1 = new Thread(new ThreadStart(() => { test(3);})); 
     Thread t2 = new Thread(new ThreadStart(() => { test(2);})); 
     Thread t3 = new Thread(new ThreadStart(() => { test(1);})); 

     t1.Start(); 
     t2.Start(); 
     t3.Start(); 

     while (true) 
      Thread.Sleep(500); 
    } 
} 

回答

6

的錯誤是換鎖對象

要脈搏[全部]你必須有鎖。它看起來像像你有一個鎖,但如果你仔細看你重新分配代碼yyy,所以這是一個不同的對象

由於這個原因,鎖定對象通常是readonly字段。

此外,鎖定盒裝的值類型或字符串通常是一個壞主意;最合適的鎖定對象是:

private readonly object syncLock = new object(); 

(可另外static如果需要)

作爲一個私有實例避免意外的鎖衝突; beig readonly避免意外重新分配。