2013-11-03 4 views
2

내가 부스트 원자력 문서를 통해가는 memory_order_release``Boost.Atomic 메모리 모델을 이해하는 데 도움이 필요하고 나는 다음과 같은 예를 통해 온 :

atomic<int> a(0); 

thread1: 
    ... /* A */ 
    a.fetch_add(1, memory_order_release); 

thread2: 
    int tmp = a.load(memory_order_acquire); 
    if (tmp == 1) 
    { 
    ... /* B */ 
    } 
    else 
    { 
    ... /* C */ 
    } 

는 지금은 조금 memory_order_release 및 memory_order_acquire에 관한 혼동 여전히입니다.

릴리스를 수행

memory_order_release : 문서는 그들을 설명 조작. 비공식적으로 말하면, 이전의 모든 메모리 조작이이 지점을 지나서 재정렬되는 것을 방지하십시오.

memory_order_acquire

획득 작업을 수행합니다. 비공식적으로 말하면,이 시점 이전에 메모리 작업이 재정렬되지 않도록하십시오.

나는 아직도 약간 혼란 스럽다. 위의 정의가 의미하는 바를 설명 할 수 있고 또한 A와 C가 어떻게 충돌 할 수 있는지를 설명해 주시면 감사하겠습니다.

답변

2

이 정의는 A에서 메모리 조작이 a (정의에서 릴리스의 정의로) 이후에 다시 정렬 될 수 없음을 의미합니다. 그리고 B 또는 C의 연산 중 어느 것도 다른 스레드 (의 정의는 질문에서을 획득 함)에서 a의로드를 선행 할 수 없습니다.

이제이 예는 a에서 작동하거나 적어도 a에 쓰는 다른 코드가 없다고 가정합니다. B가 실행되면 tmp에로드가 발생하면 a의 값이 1임을 의미합니다. a의 값이 1 인 경우 앞에 fetch_add을 실행해야합니다 (fetch_addload과 동기화 됨). 이는 A에서 실행 된 코드가 완료되었음을 의미합니다. 특정 코드 경로가 충돌하는 경우, 작업의 순서는 다음과 같습니다

A 
a.fetch_add(1,memory_order_release); 
int tmp = a.load(memory_order_acquire); 
B 

이제 다른 옵션이 load이 값을 발생했을 때 여전히 첫 번째 스레드가를 실행하지 않은 것을 의미 0 점이다 fetch_add이지만 어디에서 실행되는지는 보장 할 수 없습니다. 스레드 2가 C를 실행하면 A는 여전히 실행 중일 수 있습니다 (또는 시작되지 않았거나 완료되었을 수 있습니다).

A와 B가 모두 동일한 변수에 액세스하는 경우 원자는 B가 A가 이미 완료된 후에 만 ​​실행될 수 있기 때문에 충돌이 없습니다. 반면에 C에 대한 보증은 주어지지 않습니다. 따라서 A와 C가 같은 변수를 터치하고 적어도 하나가 그것에 쓰면 경쟁 조건이 있습니다.

+0

답장을 보내 주셔서 감사합니다. 또 하나의 질문입니다. 게시물의 시작 부분에서 '정의에 따르면 A에서의 메모리 연산이 상점에서 다시 정렬 될 수 없음을 의미합니다. 여기에서 재정렬이 의미하는 바가 무엇인지 설명해 주시겠습니까? "메모리 조작이 아닌 순서로 재정렬 할 수 있습니까?" – MistyD

+0

@MistyD : A의 마지막 줄에 변수'b'에 대한 업데이트가 있으면'memory_order_release'는 컴파일러 나 CPU가'a'에 대한 업데이트 후에'b'에 쓰기를 재주문하지 않도록합니다. 그 보장이 없다면 B가'b'에 접근하면 경쟁 조건이 생길 수있다. –