원자 지침 및 가변 업데이트 가시성
-
06-07-2019 - |
문제
가장 일반적인 플랫폼에서 (가장 중요한 것은 X86; 일부 플랫폼은 멀티 스레딩에 유용한 보장을 거의 제공하지 않지만 희귀 한 카운터 샘플에 관심이 없음)는 다음과 같은 코드가 안전합니까?
스레드 1 :
someVariable = doStuff();
atomicSet(stuffDoneFlag, 1);
스레드 2 :
while(!atomicRead(stuffDoneFlag)) {} // Wait for stuffDoneFlag to be set.
doMoreStuff(someVariable);
원자 OPS의 표준, 합리적인 구현을 가정합니다.
- 스레드 1의 할당입니다
someVariable
이전에 완료하도록 보장됩니다atomicSet()
호출 되나요? - 스레드 2는 과제를 볼 수 있도록 보장됩니다
someVariable
전화하기 전에doMoreStuff()
그것이 읽는 경우stuffDoneFlag
원자 적?
편집 :
- 내가 사용하고있는 원자력 작전의 구현에는 x86이 포함되어 있습니다.
LOCK
도움이되는 경우 각 작업에 대한 지침. - 추정하다
stuffDoneFlag
어떻게 든 제대로 지워집니다. 얼마나 중요하지 않습니다. - 이것은 매우 단순화 된 예입니다. 나는 당신이 문제의 전체 맥락을 이해할 필요가 없도록 이런 식으로 만들었습니다. 나는 그것이 효율적이지 않다는 것을 알고 있습니다.
해결책
실제 X86 코드에 스레드 1의 AtomicSet의 매장에 상점이 있고 스레드 2의 AtomicRead에서로드 후 약간의 부하가 있으면 괜찮을 것입니다. 인텔의 소프트웨어 개발자의 매뉴얼 볼륨 3A 8.2 절에서 x86에 대한 메모리 모델을 지정하고 스레드 내 스토어 스토어 및로드로드 제약 조건으로 충분해야합니다.
그러나 컴파일러가 원자 운영에서 사용하는 상위 수준의 언어에서 생성 된 지침을 재정렬하는 것을 방해하지 않을 수 있습니다.
다른 팁
1) 예
2) 예
두 작업.
이 코드는 스레드가 안전하게 보이지만 귀하의 효율성에 의문 스핀 락 (while 루프) 아주 짧은 시간 동안 만 회전하지 않는 한. 주어진 시스템에서 스레드 2가 모든 처리 시간을 완전히 호그하지는 않는다는 보장은 없습니다.
실제 동기화 프리미티브를 사용하는 것이 좋습니다 ( 부스트 :: 조건 _variable 스핀 잠금 장치에 의존하는 대신 여기에서 원하는 것입니다.
원자 지침은 스레드 2가 스레드 1을 기다리며 스레드 2가 진행되기 전에 변수를 설정하기 위해 스레드 1을 기다립니다. 그러나 두 가지 주요 문제가 있습니다.
1) someVariable
선언해야합니다 '휘발성 물질'컴파일러가 최적화되지 않도록하기 위해 등록부에 저장하거나 쓰기를 연기하는 할당됩니다.
2) 두 번째 스레드는 신호를 기다리는 동안 차단됩니다 ( 스핀 로킹). 귀하의 플랫폼은 아마도 훨씬 더 나은 잠금 및 신호 전기 및 메커니즘을 제공하지만 비교적 간단한 개선은 간단하게 개선 될 것입니다. sleep()
스레드 2에서 while()
신체.
Dsimcha는 다음과 같이 썼습니다.이것은 사실이 아닙니다!
시나리오를 보자 :
- STREAD2는 stuffDoneflag가 1 인 경우 약간의 평가를 시작합니다.
- Thread2가 완료되기 전에 작업 스케줄러가 작업을 방해하고 한동안 작업을 중단합니다.
- Thread1은 다시 한 번 약간의 가치에 액세스하고 메모리 컨텐츠를 변경합니다.
- 작업 스케줄러 스위치가 다시 켜져 있으며 작업을 계속하면 작업이 계속되지만 일부 변환 가능의 메모리 컨텐츠가 변경됩니다!