2010-02-26 3 views
6

C++ 응용 프로그램을 작성하고 있습니다.C++ volatile 멀티 스레딩 변수

둘 이상의 스레드가 쓰는 클래스 변수가 있습니다.

C++에서는 컴파일러없이 수정 될 수있는 모든 것을 "변경"되고 있다는 사실을 휘발성 권리로 표시해야합니까? 그래서 만약 내 코드가 멀티 쓰레드이고 다른 쓰레드가 읽는 동안 하나의 쓰레드가 var에 쓸 수 있다면, var volaltile을 표시해야합니까?

감사

는 [I int 타입 원자 인에 쓰기에 의존하고있어 이후로는 경쟁 조건이없는]!

+9

글이 원자적일 것이라고 생각하는 이유는 무엇입니까? – bmargulies

+4

나는 멀티 스레딩에 대한 전문가가 아니지만, 모든 공유 리소스에 대해 항상 잠금을 구현할 것입니다 ... –

+0

저는 임베디드 PowerPC 싱글 코어 프로세서에서 이런 종류의 작업을 수행했으며 안정적으로 작동합니다. 두 스레드가 쓰기 액세스 권한을 가질 가능성이있는 경우 (예 :'++ sharedInt'와 같은) 읽기 - 수정 - 쓰기 작업을하지 마십시오. (실제로 두 개의 쓰레드가 쓰여질 수 있다면 ** 쓰기가 제한 될 때 ** 유용하다. 예를 들어, 쓰레드 A는 sharedInt를 0에서 1로 바꿀 수있다. 반면 쓰레드 B는 쓰레드 1에서 쓰레드를 변경할 수있다. – Dan

답변

3

volatile 가변 값이나 사용법의 "직감"을 최적화하지 않도록 컴파일러에 지시합니다. 외부에서 최적화 할 수 있으므로 컴파일러에 지시하십시오.

휘발성 (volatile)은 동기화를 제공하지 않지만, int 형의 int에 쓰기를 가정하면 현실적입니다!

필자는 휘발성이 필요한지 (프로그램의 동작을 확인) 알아야하거나 일종의 동기화가있는 경우 더 중요한 사항을 알아야 할 것으로 생각됩니다.

+0

사실이 아닙니다. HPC 응용 프로그램/알고리즘을 작성할 때 일반적으로 사용하려는 아키텍처에 대해 잘 알고 있습니다. 따라서 필요없는 경우 쓸모없는 자물쇠를 추가하지 않을 것입니다. – Ben

+0

글쎄, 적어도 내 관점은 윙윙 거린다. – Ben

+0

필자는 항상 int를 쓰는 것이 원자 연산 (적어도 x86 CPU에서)이라고 생각했습니다. 당신은 원자력 작전에 관한 좋은 문서를 가지고 있습니까? –

0

잠금을 사용하지 않으면 컴파일러 나 프로세서에서 '불가능한'재주문을 수행 할 수 있습니다. int에 대한 쓰기가 원자 적이라는 보장은 없습니다.

적절한 잠금 장치를 사용하는 것이 좋습니다.

13

C++는 아직 멀티 스레딩을 제공하지 않습니다. 실제로, 휘발성은 당신이 의미하는 것을하지 않습니다. (이는 메모리가 침입 한 하드웨어를 위해 설계되었으며, 두 가지 문제는 유사하지만 휘발성이 올바른 일을하지 못하도록 충분히 다릅니다. 휘발성은 다른 mt 컨텍스트에서 사용법에 대한 언어).

개체를 하나의 스레드에 쓰고 다른 개체에서 읽으려면 구현시 필요한 동기화 기능을 사용해야합니다. 내가 아는 한, 휘발성은 그 역할을하지 않습니다.

참고로, 다음 표준은 MT를 고려할 것이고 휘발성은 아무런 역할을하지 않을 것입니다. 그래서 그것은 변하지 않을 것입니다. 동기화가 필요한 표준 정의 된 조건과이를 달성하기위한 표준 정의 된 방법이 있습니다.

+0

"실제로, 휘발성은 당신이하는 것을하지 않습니다." 뭐?? 휘발성은 변수에 대한 컴파일러 최적화를 방지하도록 설계되었습니다. 그것은 고도로, 고도로, 멀티 스레드 프로그래밍을 강력히 추천합니다. 휘발성이없는 멀티 스레드 프로그래밍을 시도하지 마십시오. 귀하의 프로그램은 수년간 정상적으로 작동하고 갑자기 갑자기 부서져 버릴 수도 있습니다. –

+0

@annoying_squid, http://stackoverflow.com/a/2485177/136208을 참조하십시오. C++ 11부터'std :: atomic <>'은 휘발성 코드가 제공 할 수있는 것을 얻는 방법 일 것입니다. – AProgrammer

-4

휘발성으로 문제가 해결됩니다. 시스템의 모든 캐시간에 일관성을 보장합니다. 그러나 각 R 또는 W 액세스에 대한 메모리의 변수를 업데이트하므로 비효율적입니다. 대신 필요할 때마다 메모리 장벽을 사용하여 간단하게 구성 할 수 있습니다. (대부분 PM100 코멘트에 대한) http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Atomic-Builtins.html

편집 : 당신이 또는 GCC/ICC 작업하는 경우 동기화 내장 기능에 봐 내가 인용 뭔가를 찾을 수 있도록 내 믿음 참조 아니라는 것을 이해 :)

volatile 키워드는 특정 비동기 이벤트가있을 때 코드가 올바르지 않게 만드는 컴파일러 최적화를 방지하기 위해 고안되었습니다.예를 들어,당신은 컴파일러가 더 흥미 Dr Dobb's

에서 레지스터

에 캐시하는 것이 허용되지 않으며, 원시적 변수가 같은 휘발성 선언하는 경우 :

휘발성 필드 선형화 있습니다. 휘발성 필드를 읽는 것은 잠금을 얻는 것과 같습니다. 작업 메모리가 무효화되고 휘발성 필드의 현재 값이 메모리에서 다시 읽 힙니다. 휘발성 필드를 작성하는 것은 잠금을 해제하는 것과 같습니다. 휘발성 필드는 즉시 메모리에 다시 기록됩니다. (이되지 자성에 대한 모든 일관성에 관한 것입니다) 에서

멀티 프로그래밍의 예술, 모리스 헐리 히 & 니르 쉐빗

잠금은 잠금하지 않는 경우, 당신이해야합니다, 메모리 동기화 코드를 포함 뭔가를하고 휘발성 키워드를 사용하는 것이 아마도 당신이 할 수있는 가장 간단한 일입니다. (메모리가 주소 공간에 묶여있는 외부 장치 용으로 설계되었다고해도, 여기에 요점이 아닙니다.)

+0

왜이 응답은 downvoted입니까? – anon

+1

잘못 되었기 때문입니다. 휘발성 메모리 캐시와 아무 관련이 없습니다. – pm100

+0

@ pm100, 이건 내가 동의하지만, 캐시와 관련이있다. 내 편집을 참조하십시오. – Ben

4

예, 필요합니다. 코드 생성기가 변수를 레지스터에 저장하고 항상 메모리에서 읽고 쓰는 코드를 생성하지 않도록합니다. 대부분의 코드 생성기는 기본 CPU 워드와 크기가 동일한 변수에 원자성 보장을 제공 할 수 있으므로 변수가 캐시 라인 경계를 넘을 수 없도록 메모리 주소가 정렬되도록합니다.

그러나 이것은 최신 멀티 코어 CPU에서 매우 강력한 계약이 아닙니다. 휘발성은 이 아니며은 다른 코어에서 실행되는 다른 스레드가 변수에 대한 업데이트를 볼 수 있음을 약속합니다. 이를 위해서는 일반적으로 CPU 캐시를 비우는 명령 인 메모리 장벽이 필요합니다. 장벽을 제공하지 않으면 실은 자연히 그러한 플러시가 발생할 때까지 계속 실행됩니다. 결국 스레드 스케줄러가 스레드 스케줄러를 제공하도록 바인딩됩니다. 밀리 초가 걸릴 수 있습니다.

이와 같은 세부 사항을 처리하고 나면 결국 스레딩 라이브러리에서 제공하는 것보다 더 빠를 가능성이없는 조건 변수 (일명 이벤트)를 다시 작성하게됩니다. 또는 테스트를 거쳤습니다. 자신 만의 것을 발명하지 말고, 실을 꿰는 것이 딱딱해질만큼 힘들다. 매우 기본적인 기본 요소가 견고하다는 것을 확신하지 못하는 FUD가 필요 없다.

+2

휘발성은 절대 최소값이 아닙니다. 그것은 최소값보다 훨씬 낮습니다. 최소값은 공유 변수 주변에서 읽기/쓰기 순서 재 지정을 방지해야합니다. – jalf

+0

@ jalf - "절대 최소"보다 몇 배나 많은 눈금을 고려해야합니까? –

+0

그냥 하나 : "그 아래";) – jalf

1

필자는 volatile이 실제로 읽기에만 적용되며 특히 메모리 매핑 I/O 레지스터를 읽는 것으로 생각합니다.

이 메모리 위치에서 읽을되면 값이 변경되지 않습니다 가정하지 않도록 컴파일러에게 할 수 있습니다

: *p가 기록되어 있지 않은 경우,

while (*p) 
{ 
    // ... 
} 

을 위의 코드에서 루프 내에서, 컴파일러는 더 같이, 루프 외부에서 읽기를 이동하기로 결정 있습니다 메모리 매핑 된 I/O 포트에 대한 포인터가

cached_p=*p 
while (cached_p) 
{ 
    // ... 
} 

p 경우, 첫 번째 버전을 원하는 것이 어디 루프가 입력되기 전에 포트가 점검됩니다. y 시간.

p이 멀티 스레드 응용 프로그램의 메모리 포인터 인 경우, 여전히 쓰기가 원자 적이라는 보장은 없습니다.

+6

"(i = 0; i <10; ++ i) {j = i;}는 j = 10으로 바꿀 수 있습니다. 휘발성 물질. – stefaanv