2011-03-06 4 views
3

나는 setter가 잠금 장치로 보호되어 있지만 getter 주위에는 아무런 잠금 장치가없는 속성이 있다고합니다. 쓰기 주변의 잠금이 다른 스레드에서 새로운 읽기를 보장합니까? (.Net, 메모리 모델)

private long _myField; 
public long MyProperty 
{ 
    get { return _myField; } 
    set { lock(whatever) _myField = value; } 
} 

오히려 Monitor.Exit을 (그러나 판독) 글 동기 로크 또는 외에도 volatile write을 야기한다. 이제 두 개의 스레드 A와 B가 있다고 가정하면 다음 순서가 발생합니다.

  1. A는 현재 값 MyProperty을 읽습니다.
  2. B는 MyProperty에 새 값을 씁니다.
  3. A는 MyProperty의 현재 값을 다시 읽습니다.

Q : 이제 A가 새로운 값을 볼 수 있습니까? 아니면 우리의 잠금 장치가 B가 주 메모리에 적시에 기록하도록 보장 하였지만, 다른 스레드가 새로운 값을 읽지는 않았는가? 아니면 우리가 .NET 2+ 또는 "약한"ECMA 구현에서 실행 중인지 여부에 따라 답변이 달라질 수 있습니까?

답변

3

아니요, 읽기에 명시적인 메모리 장벽이 없기 때문에 새로운 값을 볼 수있는 "보장"되지 않습니다.

ReaderWriterLockSlim을 사용하면 a) 서로 쓰기가 잠기고 b) 읽기가 항상 새로운 값을 가져 오는 것을 확인할 수 있습니다.

private readonly ReaderWriterLockSlim _myFieldLock = new ReaderWriterLockSlim(); 
private long _myField; 
public long MyProperty 
{ 
    get 
    { 
     _myFieldLock.EnterReadLock(); 
     try 
     { 
      return _myField; 
     } 
     finally 
     { 
      _myFieldLock.ExitReadLock(); 
     } 
    } 
    set 
    { 
     _myFieldLock.EnterWriteLock(); 
     try 
     { 
      _myField = value; 
     } 
     finally 
     { 
      _myFieldLock.ExitWriteLock(); 
     } 
    } 
} 
+0

주 : OP 코드'value = _myField'는 실수 한 것처럼 보이므로 '_myField = value' (으)로 변경했습니다. –

+1

RWLS의 요점은 무엇입니까? getter 및 setter의 lock 키워드는 * lots * 오버 헤드가 적은 두 개의 스레드에 대해서도 마찬가지로 작동합니다. –

+0

@ hans-passant 더 많은 스레드가 동시에 읽히면 어떻게 될까요? –

1

Getter에서 Interlocked.Read를 사용한 경우 항상 새 값을 읽어야합니다.