2008-10-05 2 views
1

멀티 스레드 코드에서 인스턴스를 여러 스레드에서 읽거나 쓸 수있는 경우 이러한 작업을 안전하게 수행하려면 잠글 필요가 있습니다.MTA에서 쉽게 잠금 만들기

코드를 통해 잠금을 설정하고 잠금 문을 작성하는 반복을 피하기 위해 잠금을 처리 할 일반 클래스를 만들었습니다.

개념적으로 나는 무엇이 있습니까? 이건 잘 될거야, 그렇지?

public class Locked<T> where T : new() 
{ 
    private readonly object locker = new object(); 

    private T value; 

    public Locked() 
     : this(default(T)) 
    { } 

    public Locked(T value) 
    { 
     this.value = value; 
    } 

    public T Get() 
    { 
     lock (this.locker) 
     { 
      return this.value; 
     } 
    } 

    public void Set(T value) 
    { 
     lock (this.locker) 
     { 
      this.value = value; 
     } 
    }  
} 

그리고 그것의 예

클래스에서 사용되는 :

자동화 된 방법으로 또한, 어떻게, 이런 일을 테스트 할
private Locked<bool> stopWorkerThread = new Locked<bool>(); 

public void WorkerThreadEntryPoint() 
{ 
    while (true) 
    { 
     if (this.stopWorkerThread.Get()) 
     { 
      break; 

} 

(예를 들어 단위 테스트를 작성)?

마지막으로, 나는 ++ 및 구현하기 위해 무엇을 할 수 있는지 - 연산자를,이 문제를 방지하려면 :

 this.runningThreads.Set(this.runningThreads.Get() + 1); 

답변

3

가져 오기/세트의 기간에 대해서만 잠금 그; 물론, 많은 일반적인 경우에 이것은 어쨌든 단순히 데이터 크기 때문에 원자적일 것입니다.

그러나 사실상 대부분의 잠금은 추가 기능을 사용하지 않는 콜렉션이별로 도움이되지 않는다는 것과 같은 방식으로 이보다 더 길어야합니다. 호출자는 일반적으로 하나의 잠금을 필요로합니다. 업데이트하면 "시퀀스"를 추가하십시오.

bool처럼 단순한 경우, "휘발성"은 훨씬 간단하게 문제를 해결할 수 있습니다. 특히 루프 종료를위한 것일 때 특히 그렇습니다.

[MethodImpl (MethodImplOptions.Synchronized)] - 개인적으로 개인용 잠금 개체 (예 : 사용했던 것처럼)를 사용하여 개체에 대한 외부 사람들의 잠금 문제를 방지 할 수 있습니다 (위의 "this" 자물쇠로).

단위 테스트의 경우이 작업이 처음에는 부적절하다는 것을 증명할 항목이 필요합니다. 작업이 너무 작기 때문에 (그리고 대부분의 데이터 유형에 대해 원자 적입니다.) 어려울 수 있습니다. 피할 수있는 다른 것들 (휘발성도 수정 됨) 중 하나가 레지스터에 캐싱되고 있지만, 최적화와 캐쉬가 깨진 것을 증명하기는 어렵습니다.

자물쇠 래퍼에 관심이있는 경우 기존 코드는 this과 같다고 생각할 수 있습니다.

1

위의 코드는 잠재적 인 실제 멀티 스레딩 문제가 많으며 실제 상황에서는 이와 같은 것을 사용하지 않을 것입니다. 예 :

this.runningThreads.Set(this.runningThreads.Get() + 1); 

여기에는 상당히 분명한 경쟁 조건이 있습니다. Get() 호출이 반환되면 개체가 더 이상 잠기지 않습니다. 실제 게시물 또는 사전 증분을 수행하려면 카운터는 Get 전에 Set보다 먼저 잠글 필요가 있습니다.

당신이하고있는 모든 작업이 동기 읽기 인 경우에도 항상 전체 잠금을 수행 할 필요는 없습니다.

더 나은 잠금 인터페이스는 (내가 생각하기에) 사용자가 명시 적으로 인스턴스를 잠글 것을 요구합니다.내 경험이 C로 주로 ++ 그래서 나는 완전히 구현을 권장하지 않습니다,하지만 내 선호하는 구문은 다음과 같이 보일 수 있습니다 :

using (Locked<T> lock = Locked<T>(instance)) 
{ 
    // write value 
    instance++; 
} 

// read value 
print instance; 
+0

예제 코드는 잠금 (예)하지 않는 한 작동하지 않을 것입니다 다른 곳에서 선언과 모든 발신자에게 다시 사용됩니다. 그렇지 않으면 각 발신자가 다른 잠금 장치를 사용하여 목적을 이깁니다. 그리고 나서 객체와 lock (obj)을 선언하는 것이 더 간단 할 것입니다. –

+0

글쎄요, 나는 잠긴 상태의 구현 세부 사항을 대기 상태로 두는 것이었지만,이 경우 잠금은 locked <> 클래스가 아닌 인스턴스 (Locked <>)를 사용하면 잠긴 <> 클래스가 방해가됩니다. –

관련 문제