2011-01-31 3 views
2

다음 코드를 작성했습니다.멀티 스레딩 : 속성 잠금 - 정확합니까?

static readonly object failedTestLock = new object(); 

public static Dictionary<string, Exception> FailedTests 
{ 
    get 
    { 
     lock (failedTestLock) 
     { 
      return _failedTests; 
     } 
    } 
    set 
    { 
     lock (failedTestLock) 
     { 
      _failedTests = value; 
     } 
    } 
} 

public void RunTest(string testName) 
{ 
    try 
    { 
     //Run a test 
    } 
    catch (Exception exception) 
    { 
     // ?? Is this correct/threadsafe? 
     FailedTests.Add(testName, exception); 
    } 
} 

QUESTION :
실패한 테스트를 사전에 안전하게 추가하는 올바른 방법입니까?
이 스레드 안전합니까?
FailedTests.Add가 잠금 내부에 호출되었거나 잠금 외부에 있습니까?

이것이 왜 올바른지/threadsafe인지 또는 왜 그렇지 않은지 설명 할 수 있습니까?

미리 감사드립니다

답변

9

위의 코드에 근본적인 문제는 스레드가 사전을 받고 또는 설정하는 경우에만 _failedTests에 대한 액세스를 잠그는 것입니다. 한 번에 하나의 스레드 만 사전에 대한 참조를 얻을 수 있지만 일단 스레드가 사전에 대한 참조를 가지면 잠금에 의해 제약받지 않고 스레드를 읽고 조작 할 수 있습니다.

사전에 안전하게 테스트를 추가하는 올바른 방법입니까?

아니요, 두 개의 스레드가 동시에 사전에 추가하려고하는 경우 아닙니다. 특정 순서로 읽기 및 쓰기가 발생한다고 생각하지 않습니다.

이 threadsafe입니까?

It depends what you mean by threadsafe 그러나, 어떠한 합리적인 정의에 의해서도.

는 FailedTests.Add는 잠금 내부 또는 잠금 외부에서 호출되어 있습니까?

사전 검색 (get 접근 자)은 잠금 장치 내에서 발생합니다. 이 코드는 잠금을 해제 한 후 Add을 호출합니다.

왜 이것이 올바른지/threadsafe인지 또는 왜 그렇지 않은지 설명 할 수 있습니까?

사전에 여러 스레드가 동시에 작동하는 경우 해당 스레드가 내용을 변경하는 순서를 예측할 수 없으며 읽기가 발생할시기를 제어 할 수 없습니다.

7

사전이되지 않는 스레드 안전한 액세스에서

감사, 사전 객체를 반환에만 속성 액세스가 스레드 안전하지만 당신은 Add 메서드 호출을 동기화하지 않기 때문에. 이 경우 ConcurrentDictionary<string,Exception>을 사용하거나 수동으로 Add에 전화를 동기화하십시오.

2

잠금은 컬렉션에 대한 포인터가 반환되는 매우 짧은 순간에만 유지되기 때문에 스레드가 안전하다고 생각하지 않습니다. 컬렉션에 추가 할 때 잠금이 없으므로 두 스레드가 동시에 추가하려고하면 불쾌한 오류가 발생합니다. 그래서 FailedTest.Add 코드를 잠 가야합니다.

동시 수집을 살펴보고 필요할 수도 있습니다.

감사 GJ

2

Add()에 대한 호출이 잠금 외부에 있습니다.

고유 한 Add() 메서드를 작성하여 속성을 바꿀 수 있습니다.

+0

그리고 이렇게하면 'ReaderWriterLockSlim' 사용을 고려해야합니다. – Bryan

+0

그런데 미안 해요, 내가 늦게 물어 보면. 하지만, 무엇을, 우리가 getter와 setter 둘레에 고정한다면? 이렇게하면 정의 된 순서대로 가져 와서 설정하는 측면에서 완벽한 스레드 안전성을 보장해서는 안됩니까? – icbytes

+0

@icbytes - 아니요. –