昨天關於雙重檢查鎖定的問題開始了一連串的想法,讓我無法確定一個簡單的情況。在下面的代碼中,是否有可能點擊「不再同步」的printf
?在這個簡單的例子中,這些值可能會在同一個緩存行上,所以我認爲它不太可能(假設開始的可能性大於0%)。WaitForSingleObject是否充當內存屏障?
如果答案是「不,這是不可能的」,那麼我的後續問題是,相當可預測地:爲什麼不呢?直到昨天我的思緒糾結纏繞多線程軸,我認爲代碼纔是安全的。但是現在我想知道什麼可以防止從緩存中讀取pa
或pb
之一的變量。如果pa, pb
指向簡單的全局整數變量而不是malloc的內存,它會影響嗎? WaitForSingleObject調用是否提供內存屏障?或者應該將指針聲明爲volatile?這麼多問題,幾句話。
更新:我終於找到的信息,具體說,信號同步對象的功能使用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 2009-12-28 07:05:41
感謝您的信息。你碰巧知道一個鏈接,討論等待功能和內存障礙。這就是我一直在尋找,並沒有看到它。我很可能只是失明而錯過了一些明顯的東西。 – 2009-12-28 16:47:43
你不是盲人;很難在網上找到相關信息。 MSDN在http://msdn.microsoft.com/en-us/library/ms686355%28VS.85%29.aspx上提供了相當好的概述。 – 2009-12-28 23:34:03