我在这个论坛上看到很多线程在处理从多个线程访问原始数据类型时是否需要使用同步的问题:Question 1,question 2,{{3 },question 3 ...
所以我写了一个小测试来验证这个:
我在运行4个物理内核的CPU Intel(R) Core(TM) i7 CPU 860 @ 2.80GHz
上运行了一个多小时:
#define MULTIPLIC_VAL 17
DWORD gdwSharedVal01 = MULTIPLIC_VAL;
DWORD WINAPI thread001(LPVOID lpParameter);
//Begin threads
for(int i = 0; i < 30; i++)
{
DWORD dwThreadId;
HANDLE hThread = ::CreateThread(NULL, 0, thread001, NULL, 0, &dwThreadId);
if(hThread)
{
::CloseHandle(hThread);
}
else
{
_tprintf(L"ERROR: CreateThread error %d\n", ::GetLastError());
}
}
//Wait
getchar();
BOOL checkSharedValue()
{
//RETURN:
// = TRUE if value is OK
if((gdwSharedVal01 % MULTIPLIC_VAL) == 0)
{
return TRUE;
}
return FALSE;
}
DWORD WINAPI thread001(LPVOID lpParameter)
{
srand((UINT)time(NULL));
DWORD dwThreadID = ::GetCurrentThreadId();
_tprintf(L"Thread %d began...\n", dwThreadID);
for(;;)
{
//Set value
DWORD v = rand();
v <<= 16;
v ^= rand();
v = v / MULTIPLIC_VAL;
gdwSharedVal01 = v * MULTIPLIC_VAL;
//Check value
if(!checkSharedValue())
{
//Failed
_tprintf(L"FAILED thread %d\n", dwThreadID);
}
}
return 0;
}
我没有失败。那你怎么解释呢?
答案 0 :(得分:2)
在英特尔中,对齐单词的读取和写入是原子操作(原子操作,其他处理器将看到原始值或新值)。
请注意,这并不意味着您不应提供同步机制。这个测试用例是一个线程只是在同一个变量中写入和读取新值的测试用例。如果他们提供某种涉及更新读/写操作的操作,它可能会失败(比如10个线程将变量递增100,最后的变量可能不会增加1000个!)并且没有正在运行的其他变量(编译器/ cpu重新排序可能导致其他问题)。