2011-05-04 2 views
4

이 예제에 어떤 문제가 있습니까? Monitor.PulaseAll (yyy)의 "동기화되지 않은 코드 블록에서 개체 동기화 메서드가 호출되었습니다."라는 오류가 발생합니다.Monitor.PulaseAll throws errors

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는 실수로 재 할당하는 것을 방지합니다.