2014-12-09 2 views
3

다음 코드는 찢어진 읽기로부터 안전합니까 (분리되어 있다고 생각하십니까?)?원자 조작 나사 안전 - "거울"원자 판독이 필요합니까?

이중이 (64 비트 환경에서 구현 세부 사항을 제외하고) .NET 플랫폼에서 한 번의 작업으로 기록 될 보장되지 않기 때문에 원자 쓰기 작업 ( Interlocked.Exchange())가 필요
private static double flopsErrorMargin = 0.01d; 

public static double FlopsErrorMargin { 
    get { 
     double result = flopsErrorMargin; 
     Thread.MemoryBarrier(); 
     return result; 
    } 
    set { 
     Interlocked.Exchange(ref flopsErrorMargin, value); 
    } 
} 

.

그러나 읽기 측면에서 '미러'작업이 필요합니까? 예 : 나는 값을 원자 적으로 읽지 않기 때문에 찢어진 읽기를 할 위험이 있습니까?

나는 다른 메모리 액세스 (예 : 읽기)가 다른 원자 연산과 동시에 일어날 수 없다고 생각하기 때문에 그럴 수 없다는 것이 내 접근이다. 그러나 나는 약간의 확인을 원한다!

+2

매우 많은 다른 저수준 멀티 스레딩 문제와 마찬가지로 가장 좋은 방법은 이러한 유형의 질문을 다루지 않아도되는 코드를 작성하는 것입니다. 상당히 보수적 인 동기화를 통해 높은 수준의 멀티 스레딩 프레임 워크를 사용하는 데 시간을 허비하는 것은 너무 느려서 이런 질문을하지 않아도된다는 것을 확실히 알아야합니다. – Servy

+0

원칙적으로 안전하지는 않습니다. 실제로는 (적어도 x86의 경우) 찢어진 읽기를 재생할 수 없었습니다. 자세한 내용은 [이 답변] (http://stackoverflow.com/questions/3679209/why-doesnt-this-code-demonstrate-the-non-atomicity-of-reads-writes/3679400#3679400)을 참조하십시오. 나는이 결과를 관찰하는 것에 놀랐다. 물론, 보장되지 않는 행동에 의존하지 않는 것이 가장 좋습니다. –

+0

@DanBryant 물론, 다음과 같은 것이 있으면 주목할만한 가치가 있습니다.00001 %의 코드에서 실패 할 확률은 실제로 발생할 확률이 매우 낮습니다. 프로그램은 매우 크고 복잡해야만 눈에 띄게 만들지 못할 확률은 이처럼 버그를 진단하는 것이 매우 어렵습니다. – Servy

답변

3

아니요, 찢어진 읽기가 가능합니다. 필드 액세스가 데이터를 읽고 중간 부분에 Interlocked.Exchange으로 삽입되었다고 가정하면 다른 32 비트는 Exchange의 업데이트 된 값이되고 따라서 찢어진 읽기가 생성됩니다.

원자 읽기의 경우, Interlocked.Read (32 비트 컴퓨터에서)을 사용해야합니다.

64 비트 읽기 작업이 이미 원자 적이기 때문에 읽기 방법은 64 비트 시스템에서는 필요하지 않습니다. 32 비트 시스템 은, 64 비트 값은 찢기가 가능하다는 것을 의미

읽기

를 사용하여 수행 않는 작업 원자하지 읽었다.

당신은 정의 할 수 있습니다 당신이 Interlocked.Read(long)는 내부적으로 구현되는 방법입니다

public static double Read(ref double location) 
{ 
    return Interlocked.CompareExchange(ref location, 0d, 0d); 
} 

을 다음과 같이 double에 대한 Read 원자 자체.

+1

Interlocked.Read는 double을 지원하지 않습니다. long (Int64) 변수에만 해당됩니다. –

+0

@DanBryant 사실이지만, 요점은 여전히 ​​동일합니다. 단어 크기보다 큰 읽기는 원자 적이지 않습니다. 동기화가 필요합니다. –

+1

@DanBryant이 게시물을 업데이트하여 'double'에 대해 'Interlocked.Read'를 구현하는 방법을 보여줍니다. –

2

오전 나는 값을 원자 적으로 읽지 않기 때문에 찢어진 읽기가 발생할 위험이 여전히 있습니까?

예. Interlocked.Exchange의 반환 값은 찢어지지 않으며 flopsErrorMargin결국으로 끝나는 값은 value이됩니다 (이는 Interlocked.Exchange의 두 가지 보증 임). 그러나 동기화되지 않은 읽기 액세스가 찢어 질 수 있습니다.