2009-12-28 4 views
5

어제 두 배로 확인 된 잠금에 대한 간단한 사고가 나에게 간단한 상황을 알 수없는 생각을 불러 일으켰다. 다음 코드에서 printf의 '더 이상 동기화되지 않음'을 누를 수 있습니까? 이 간단한 예제에서 값은 같은 캐시 라인에있을 가능성이 높습니다. 가능성은 낮습니다 (가능성은 0 % 이상이라고 가정).WaitForSingleObject가 메모리 장벽 역할을합니까?

대답이 "아니오, 불가능합니다."라고 말하면, 후속 질문은 오히려 예측 가능합니다 : 왜 안됩니까? 어제 멀티 스레드 액셀을 둘러싼 내 생각이 얽히고 싸울 때까지 코드가 안전하다고 생각했습니다. 하지만 지금은 변수 pa 또는 pb 중 하나에 대해 캐시에서 부실 읽기를 방지하는 것이 궁금합니다. 그리고 pa, pb이 malloc 된 메모리가 아닌 단순한 전역 정수 변수를 가리키면 중요할까요? WaitForSingleObject 호출이 메모리 장벽을 제공합니까? 아니면 포인터가 휘발성 선언되어야합니까? 매우 많은 질문을합니다.

업데이트 : 신호 동기화 개체의 기능이 memory barriers이라는 것을 구체적으로 말한 정보를 마침내 찾았습니다. 분명 했어야했지만 확실한 대답을 찾는 데 어려움을 겪고있었습니다. 그래서 나는 다시 한번 내가 그것을 모두 이해한다고 믿게 만들 수 있습니다.

int i1 = 0; 
int i2 = 0; 
int reads = 0; 
int done = 0; 
int *pa = NULL; 
int *pb = NULL; 
HANDLE hSync = NULL; 

DWORD WriteThread(LPVOID pvParam) 
{ 
    while(!done) 
     { 
     WaitForSingleObject(hSync, INFINITE); 
     (*pa)++; 
     (*pb)++; 
     ReleaseSemaphore(hSync, 1, NULL); 
     } 
    return 0; 
} 

DWORD ReadThread(LPVOID pvParam) 
{ 
    while(!done) 
     { 
     WaitForSingleObject(hSync, INFINITE); 
     if (*pa != *pb) 
     { 
     printf("No longer in sync: %d, %d\n", *pa, *pb); 
     exit(1); 
     } 
     ReleaseSemaphore(hSync, 1, NULL); 
     reads++; 
     } 
    return 0; 
} 

int main(int argc, char* argv[]) 
{ 
    DWORD dwID; 

    // malloc'd memory 
    pa = (int*)malloc(sizeof(int)); 
    pb = (int*)malloc(sizeof(int)); 

    // Is a simple global variable different? 
    //pa = &i1; 
    //pb = &i2; 

    *pa = 0; 
    *pb = 0; 

    hSync = CreateSemaphore(NULL, 1, 1, NULL); 
    CreateThread(NULL, 0, WriteThread, NULL, 0, &dwID); 
    CreateThread(NULL, 0, ReadThread, NULL, 0, &dwID); 

    while (*pa < 1000000) 
     Sleep(1); 
    done = 1; 

    return 0; 
} 

답변

4

메모리가 어디에 있는지는 중요하지 않으며 캐시 일관성에 관한 것이면 변수를 volatile로 선언해도 문제가 해결되지 않습니다. 휘발성 (volatile)의 의미는 스레드 안전을 위해 필요하거나 충분하지 않습니다. 그것을 사용하지 마십시오!

C/C++ 레벨에서 pa 및 pb는 레지스터에 캐시 될 수 있지만 함수 호출 후에는 부실로 간주됩니다. CPU 수준에서 모든 대기 함수는 장벽을 사용하여 모든 것이 예상대로 작동하는지 확인합니다.

+0

+1 정확히 말하려고했던 것. – tony

+0

정보를 제공해 주셔서 감사합니다. 대기 기능과 메모리 장벽을 설명하는 링크를 알고 계십니까? 그것이 내가 찾고 있었고 그것을 보지 못했던 것이다. 나는 눈이 멀었고 명백한 무언가를 놓쳤을 가능성이 큽니다. –

+2

당신은 장님이 아닙니다. 온라인으로 관련 정보를 찾는 것은 어렵습니다. MSDN은 http://msdn.microsoft.com/en-us/library/ms686355%28VS.85%29.aspx에서 합리적으로 좋은 개요를 제공합니다. –

관련 문제