2012-01-17 6 views
4

다음 개체 스레드가 안전합니까? 하나의 인스턴스를 만들고 두 개 이상의 스레드를 사용하여이 방법을 사용하는 것이 좋을까요?다음 객체 스레드가 안전합니까?

public class ASyncBuffer<T> 
{ 
    readonly object _locker = new object(); 
    private T _value; 
    private bool _dirty; 

    public T GetValue() 
    { 
     lock (_locker) 
     { 
      _dirty = false; 
      return _value; 
     } 
    } 

    public void SetValue(T value) 
    { 
     lock (_locker) 
     { 
      _dirty = true; 
      _value = value; 
     } 
    } 

    public bool Dirty 
    { 
     get 
     { 
      lock (_locker) 
      { 
       return _dirty; 
      } 
     } 
    } 
} 
+0

'readonly object _locker'에'private'를 추가하십시오. 그것 없이는 프로젝트의 다른 객체가'_locker'를보고 자체 잠금을 추가 할 수있었습니다. –

+0

_locker를 잠그고 잠그지 않는 이유 (this)? –

+2

@ Hand-E-Food, 아니요, 기본적으로'private'입니다. 더 명시 적으로 말하면 더 낫습니다. –

답변

7

개체 자체는 스레드로부터 안전하지만 개체의 사용도 고려해야합니다. 예를 들어, 사용은 다음과 같습니다 경우 : Dirty의 값이 실제로 가치를 얻을 때 당신이 그것을 확인시 사이에 변경 될 수 있기 때문에 사용이 스레드에 안전 아니라고

if (buffer.Dirty) { 
    var obj = buffer.GetValue(); 
} 

.

그 문제를 방지 (및 잠금의 최소 사용을), 당신은 너무처럼 사용하고자하는 것 : 재산 자마자, 재산 자체를 액세스 할 경우에만

if (buffer.Dirty) { 
    lock(buffer) { 
     if (buffer.Dirty) { 
     var obj = buffer.GetValue(); 
     } 
    } 
} 
+0

그래서 다음과 같이해야합니다 : lock (_buffer) { if (buffer.Dirty) { var obj = buffer.GetValue(); } } ? – user1149942

+0

@user - 올바른 대답을 설명하기 위해 대답을 업데이트했습니다. –

+0

흠, 그래서 같은 개체를 사용하여 설정 및 설정을 잠글 필요가 없습니까? – user1149942

-3

AFAIK, 이것은 스레드 안전 프로그램이 아닙니다. 당신의 getter와 setter는 다른 lock을 가질 것입니다. 자세한 내용은 thread을 참조하십시오.

+0

다른 잠금 장치가 무슨 의미인지 이해할 수 없습니다. 그리고 그 고리는 나를 돕지 못합니다. – Fantius

+3

그는 단일 읽기 전용 잠금 개체를 가지고 있습니다. 그는 재산 자체의 가치를 잠그지 않으므로 나는 당신이 말하는 것이 사실이라고 생각하지 않습니다. –

+0

실제로 그들은 동일한 객체를 사용하여 잠그기 때문에 속성 주변의 잠금은 스레드로부터 안전합니다. 그러나 (링크에서와 같이) 객체의 내부 상태를 변경하는 것은 완전히 다른 문제입니다. –

1

요약하면 no : 입니다.

값의 소유권을 양도 한 후에는 어떻게 될지에 대해 절대 보장 할 수 없습니다. 이것은 특히 _value에 의지하여 if 문과 같은 것으로 특정 값 (말장난 없음)을 사용하는 경우 더욱 두드러집니다. 그런 일이 발생하면 _value은 읽을 때 부분 쓰기 상태가되지 않습니다.

더티 플래그에 대해서도 마찬가지입니다 ... 솔직하게 더티 플래그로 더 발음됩니다.

이 경우 고려 : 그런 의미에서

Thread 1 calls ASyncBuffer.SetValue(someValue) // sets the dirty flag to true 
Thread 1 checks ASyncBuffer.Dirty // should be true 
Thread 2 calls ASyncBuffer.GetValue() // sets the flag to false 
Thread 1 calls ASyncBuffer.GetValue() // you expect the dirty flag to be true, but it's not 

를, 그것은 스레드 안전 아닙니다.

0

YES하지만 사용되는/할당되면 그것은 스레드 안전 방식으로 조작되는 내부 상태를 처리하기 위해 조작되는 객체에 달려 있습니다.

+0

아우, 내부적으로이 모든 것들을 처리 할 방법이 없으므로 객체 외부에서 걱정할 필요가 없습니까? :( – user1149942

+0

객체의 구현 내용은 다음과 같습니다. 당신은 각 속성/메소드를 보호하기 위해 다시 잠금을 사용할 수 있습니다 (필요에 따라 1 개 또는 여러 개의 잠금 객체 사용) –

0

예, 그렇지만 사용하지 않았을 수 있습니다.

"더티"인 경우에만 값을 검색한다고 가정합니다. 각 검색에서 해당 값이 지워 지므로 반대 값을 볼 수 없습니다. 그러므로 당신은 할 것 : 다른 스레드가 동시에 GetValue()를 호출하는 경우

if(buff.Dirty) 
{ 
    T val = buff.GetValue(); 
    //operations on val. 
} 

그러나, 다음 Dirty 지금은 false입니다.

따라서 하나의 판독기 스레드 (이 경우 다중 작성기 스레드는 정상적으로 반대 방향으로 Dirty을 변경하기 때문에 괜찮습니다.)에만 사용하면 안전합니다.

여러 독자를 가질 수 있다면, 같은 것을 추가하는 것을 고려 : 당신이 그런

public bool GetIfDirty(out T value) 
{ 
    lock (_locker) 
    { 
    if(!_dirty) 
    { 
     value = default(T); 
     return false; 
    } 
    _dirty = false; 
    value = _value; 
    return true; 
    } 
} 

모두 테스트 Dirty을 할 수 있으며 원하는 경우 같은 스레드 작업에서 값을 구하십시오.

관련 문제