2013-08-08 2 views
7

두 스레드에서 액세스되는 변수 int foo이 있습니다. 레이스 컨디션 문제가 없다고 가정하면 (액세스는 뮤텍스에 의해 보호되고, 모든 작업은 원자 적이며, 경쟁 조건으로부터 보호 할 다른 방법도있다.) 더 나은 이름이 없다는 이유로 "레지스터 캐싱"문제가 여전히있다. 여기서 컴파일러는 변수들 사이에 기록되지 않고 회 판독되면, 그 동일한 값이라고 가정 할 수 있으며, 다음처럼 얻어 것을 "최적화"수스레드간에 변수를 동기화하는 'volatile`

while(foo) { // <-may be optimized to if(foo) while(1) 
    do-something-that-doesn't-involve-foo; 
} 

또는

if(foo) // becomes something like (my assembly is very rusty): mov ebx, [foo]; cmp ebx, 0; jz label; 
    do-something-that-doesn't-involve-foo; 
do-something-else-that-doesn't-involve-foo; 
if(foo) // <-may be optimized to jz label2; 
    do-something; 

foovolatile으로 표시합니까?이 문제가 해결 되었습니까? 한 스레드의 변경 사항이 다른 스레드에 도달 할 것을 보장합니까?

그렇지 않다면 어떻게해야합니까? Linux/Windows (아마도 별도의 솔루션), 아니 C++ 11에 대한 솔루션이 필요합니다.

+0

표준에서 인용문을 볼 때마다 스레드에 대해 더 이상 volatile을 사용하지 않아도된다는 것을 기억합니다. C++에서는 – aaronman

+3

http : // stackoverflow를 찾으려고합니다.com/questions/4557979/when-to-use-volatile-with-multi-threading –

+1

여기에있는 문제는 "경쟁 조건 문제가 없다고 가정합니다"입니다. 그것은 ** ENORMOUS ** 가정입니다. –

답변

11

필요한 것은 메모리 장벽입니다.

MemoryBarrier(); 

또는

__sync_synchronize(); 

편집 : 나는 흥미로운 부분을 굵은 글씨로 여기에 위키 기사 (http://en.wikipedia.org/wiki/Memory_barrier#cite_note-1) 및 관련 참조 여기 (http://www.rdrop.com/users/paulmck/scalability/paper/whymb.2010.07.23a.pdf)

에 대한 링크의에 대답했습니다 다른 질문 (위키 백과에서) : C 및 C++에서 volatile 키워드는 C 및 C++ 프로그램이 메모리 매핑 I/O에 직접 액세스 할 수 있도록하기위한 것입니다. 메모리 매핑 I/O는 일반적으로 소스 코드에 지정된 읽기 및 쓰기가 누락없이 지정된 순서대로 이루어 지도록 요구합니다. 컴파일러에 의한 읽기 및 쓰기의 누락 또는 재정렬은 프로그램과 메모리 매핑 I/O에 의해 액세스 된 장치 간의 통신을 중단시킵니다. C 또는 C++ 컴파일러는 휘발성 메모리 위치에 대한 읽기 및 쓰기를 재정렬하거나 휘발성 메모리 위치에 대한 읽기 또는 쓰기를 생략 할 수 없습니다. 휘발성 키워드는 캐시 일관성을 유지하기 위해 메모리 장벽을 보장하지 않습니다. http://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-1-of-2 http://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-2-of-2 : 따라서 혼자 "휘발성"의 사용은

확인이 하나의 아웃, 피사체에 큰 설명을 제공한다 [1] 모든 시스템과 프로세서 스레드 간 통신을위한 변수를 사용하는 것이 충분하지 않습니다

9

액세스가 뮤텍스로 보호되는 경우 걱정할 필요가 없습니다. 여기서 volatile 키워드는 쓸모가 없습니다. 뮤텍스는 전체 메모리 장벽이므로 외부에서 볼 수있는 주소를 가진 객체는 뮤텍스 잠금 또는 잠금 해제 호출을 통해 캐시 할 수 없습니다.

+0

참. 뮤텍스는 캐시 일관성을 유지합니다. – MasterPlanMan

+0

명확성 : 캐시를 통해 나는 기계 수준의 캐시뿐만 아니라 컴파일러의 값 캐시를 레지스터에 포함 시켰습니다. –

1

volatile 키워드는 원래 값이 하드웨어에 의해 변경 될 수 있음을 나타 내기 위해 도입되었습니다. 이것은 하드웨어 장치에 메모리 맵 레지스터 또는 메모리 버퍼가있을 때 발생합니다. 올바른 접근 방식은이 용도로만 사용하는 것입니다.

모든 현대 동기화 언어 구문 및 동기화 라이브러리는이 키워드를 사용하지 않습니다. 응용 프로그램 수준 프로그래머도 동일한 작업을 수행해야합니다.

관련 문제