어제 두 배로 확인 된 잠금에 대한 간단한 사고가 나에게 간단한 상황을 알 수없는 생각을 불러 일으켰다. 다음 코드에서 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;
}
+1 정확히 말하려고했던 것. – tony
정보를 제공해 주셔서 감사합니다. 대기 기능과 메모리 장벽을 설명하는 링크를 알고 계십니까? 그것이 내가 찾고 있었고 그것을 보지 못했던 것이다. 나는 눈이 멀었고 명백한 무언가를 놓쳤을 가능성이 큽니다. –
당신은 장님이 아닙니다. 온라인으로 관련 정보를 찾는 것은 어렵습니다. MSDN은 http://msdn.microsoft.com/en-us/library/ms686355%28VS.85%29.aspx에서 합리적으로 좋은 개요를 제공합니다. –