2009-10-23 4 views
1

읽고 쓸 수있는 파일이 있습니다. 나는 그 편지가 쓰여졌을 때 아무도 그 편지에 글을 쓰려고하지 않을 것입니다.멀티 스레딩 잠금 및 모니터 클래스가 작동하지 않습니다.

읽기 또는 쓰기를 허용하는 전체 기능에 잠금을 설정했지만 여전히 오류가 발생합니다. 다른 프로세스에서 사용 중이기 때문에 'FILENAME'파일에 액세스 할 수 없습니다.

public static TYPE Property{ 

get{ 
    data mydata; 
    Object obj = new object(); 
    Monitor.Enter(obj); 

    // check if data has not changed 
    // if it has not, just read 

    using (Stream stream = File.Open(fileLocation, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { 
     //.... 
    } 
    // else, if data changed, then need to write to file to save the new data 

    using (Stream stream = File.Open(fileLocation, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read)) { 
     BinaryFormatter bf = new BinaryFormatter(); 

     try { 
      bf.Serialize(stream, (data); 
     } 
     //DONE processing 

     Monitor.Pulse(obj); 
     Monitor.Exit(obj); 
     return data 
} 

답변

10

당신은 속성이 호출 될 때마다에 고정하는 새로운 모니터를 만드는 것입니다. 같은 모니터를 잠글 필요가 있습니다. 그렇지 않으면 잠글 때 아무런 문제가 없습니다.

"잠금"문을 사용해야합니다. 결코 기다릴 필요가 없으므로 펄스가 울리지 않습니다. 현재 예외가 발생하면 잠금이 "누출"됩니다. 보통은 정말 나쁜 문제이지만, 어쨌든 잠금을 재사용하지 않으면 문제가 가려집니다.

예를 들어

: 여담으로

private static readonly object monitor = new object(); 

public static TYPE Property 
{ 
    get 
    { 
     lock(monitor) 
     { 
      // check if data has not changed 
      // if it has not, just read 
      using (Stream stream = File.Open(fileLocation, 
        FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) 
      { 
       .... 
      } 
      // else, if data changed, then need to write to 
      // file to save the new data 
      using (Stream stream = File.Open 
         (fileLocation, FileMode.OpenOrCreate, 
         FileAccess.ReadWrite, FileShare.Read)) 
      { 
       BinaryFormatter bf = new BinaryFormatter(); 
       bf.Serialize(stream, data); 
      } 
      return data; 
     } 
    } 
} 

, 정말 속성에 기대했던 것보다 더 많은 일을하고있는 것처럼이 보인다. 방법이 더 이해되지 않을 것이라고 확신합니까?

+0

부동산 외부에이 장소를 두는 것을 의미합니까? – user176657

+0

예 - 동일한 모니터를 여러 번 사용할 수 있습니다. –

4

음, Monitor.Enter는 동일한 객체에 잠금을 설정하려는 모든 스레드의 액세스를 차단합니다. getter를 입력 할 때마다 새 객체를 생성하므로 모든 호출자는 서로에 대해 알지 못하는 새로운 자물쇠를 얻습니다.

즉, 잠금이 없습니다.

사이드 노트 - 왜 lock 문을 사용하지 않습니까? 그래도 전역 잠금 객체가 필요합니다.

+0

"당신은 여전히 ​​전역 잠금 개체가 필요합니다." – user176657

+0

바로 그거야. 모니터가 잠금을 보유하고있는 객체 (변수)는 전역이거나 잠금이 발생하는 속성 또는 메소드에 대해 로컬이 아니어야합니다. 그러면 다시 초기화되지 않습니다. – Cerebrus

1

전역 변수와 로컬 변수의 차이는 LOCK이 실제로 이해할 때 memeory에서 참조 점을 잠그는 것입니다. "Object obj = new object();"와 같은 새 객체를 인스턴스화 할 때마다 메모리에 고유 한 포인터가있는 새 객체를 만듭니다. 그래서 LOCK이 메모리의 포인트가 잠겨 있는지를 볼 때, 그렇지 않습니다. 메모리의 새로운 참조 점이고 사용하는 유일한 사람은 사용자의 속성을 입력하는 호출자입니다. Obj 변수를 전역 적으로 선언하면 항상 메모리의 같은 지점이되고 잠금의 유효성을 실제로 확인할 수 있습니다. 메모리의 해당 지점이 현재 잠겨 있거나 잠글 수 있습니다.

예 : (원유하지만 난 그게 포인트를 얻을 생각)

Object obj = new object();

는 이제 메모리에 지점이 좀 보이는 같은 :

메모리 -

* obj1 

이제 속성을 다시 입력하고 새 개체를 다시 만듭니다. 첫 번째 여행에

* obj1 
    * obj2 

, 잠금 메모리에 "OBJ1"을 확인하고 있습니다 - 메모리

... 같은 시스템 메모리는 이제 좀 보인다.귀하의 부동산으로의 첫 번째 여행자의 호출자가 Obj의 해당 인스턴스를 사용하는 유일한 사람이기 때문에, 잠그거나 잠그고 잠그는 사람은 유일합니다. 왜냐하면 그것은 메모리에있는 그 Obj 레퍼런스의 사본을보고 있기 때문입니다.

두 번째 여행에서 잠금 장치의 메모리에 "Obj2"가 표시됩니다.

전역 변수를 사용하면 메모리의 해당 지점이 계속 유지되므로 잠금은 항상 메모리의 동일한 지점을 검사합니다. 결코 움직이지 않으며 항상 메모리의 동일한 참조 점입니다. 따라서 귀하의 부동산을 이용하는 모든 호출자는 항상 메모리에서 동일한 참조 포인트를 사용하므로 예상대로 잠금이 성공합니다.

특별주의 사항 : "obj"의 사용 시간은 명시하지 않았습니다. 다중 스레드 프로세스에서 이것이 어떻게 기능 하는지를 간단히 설명합니다. 도움이되는 희망.