2010-12-07 2 views
6

내가 스레드 안전 행동해야합니다 일부 코드가이 유사합니다자물쇠와 연동 작업을 혼합해도 안전합니까?

 

protected long m_RunningValue 
protected long m_RunningCounter 
protected object m_Lock = new object(); 

public long RunningValue { get { return Interlocked.Read(m_RunningValue); } } 
public long RunningCounter { get { return Interlocked.Read(m_RunningCounter); } } 

public void DoCalculation(int newValue, int newQuantity) 
{ 
    lock(m_Lock) 
    { 
     Interlocked.Add(ref m_RunningValueA, newValue); 
     Interlocked.Add(ref m_RunningCounter, newQuantity); 
     if(Interlocked.Read(ref newQuantity) == 0) 
     { 
     ...m_RunningValue gets further modified here 
     } 
    } 
} 
 

값과 카운터 또는 경우 (...) 블록에 영향을 수있는 경쟁 조건을 모두 잠 가야 계산, 그러나 그들은 카운터와 값이 양쪽 모두를 읽으려는 시도 사이에 바뀌면 즉, 나와 100 % 괜찮습니다.

64 비트 값의 스레드 안전성 판독을 위해 읽음의 인터록이 있습니다.

  1. 안전 잠금 장치와 잠금 장치가 섞여 있습니까? 나는 그들을 혼합하는 것이 안전하지 않다는 것을 다른 웹 페이지에서 읽었으나, 이것들을 혼합하는 것이 미묘한 버그를 소개 할 수있는 좋은 방법인지 또는 시스템 레벨에서 관련 데이터 구조를 손상시킬 수있는 경우 설명을 찾을 수 없다.

  2. get() 메소드 속성 주위에 ReaderWriterSlim 잠금을 저장하는 목적을 완전히 상쇄하는 비용 (64 비트 .NET 4.0 런타임)이 있습니까? 편집 된 버전에 관해서

+0

'newQuantity'에 인터록을 읽을 필요가 없습니다. 퍼포먼스와 관련해서는 읽기와 업데이트의 상대적 혼합에 달려 있다고 생각합니다. 중요하다면 아마 추측 대신 벤치마킹해야합니다. –

+0

연동 작업과 잠금을 혼합하여 문제가 발생하는 이유가 표시되지 않습니다. – casablanca

+0

Anon의 답변이 사실 인 이유를 알게되었습니다. 인터록없이 잠금 장치 내에서 작업을 수행하는 경우 읽기 속성을 연동시켜야합니까? – Chuu

답변

5

,이 스레드 안전이 보장 하지입니다.

32 비트 플랫폼을 고려해보십시오. 즉, 64 비트 long 값은 두 번의 개별 작업에서 액세스해야합니다.

한 스레드가 숫자의 첫 번째 절반을 읽은 다음 CPU에서 스왑하고 값의 두 번째 절반을 뒤에서 변경하는 것이 가능합니다. 이제 스레드가 완전히 잘못된 값을 갖습니다.

읽기 방법과 증가, 감소시킵니다의 64 비트 과부하 및 추가 방법 만 System.IntPtr 이름이 64 시스템에서 진정한 원자 있습니다 Interlocked.Read에 대한

워드 프로세서는 명시 적 언급을 조금 길다. 다른 시스템에서는 이러한 메소드가 서로에 대해 원자 적이지만 데이터에 액세스하는 다른 방법에는 관련되지 않습니다. 따라서 32 비트 시스템에서 스레드 안전성을 유지하려면 모든 액세스과 64 비트 값은 Interlocked 클래스의 멤버를 통해 만들어야합니다.

(강조 광산)

편집 : 지금은 다시 편집 한 사용자들은이 조금 바보 보이는,하지만 난 당신이 어떤 장소에 연동하는 경우 그 지점을 만들기 위해 여기두고 있지만거야 다른 것들은 무의미합니다.