1、 Code
int Work()
{
while (m_lInterlockedData < 10)
{
InterlockedIncrement(&m_lInterlockedData);
Sleep(100);
}
printf("CInterlocked::Work end\n");
return 0;
}
起5
个线程运行Work()
函数,理论上m_lInterlockedData
最后运行的结果应该是10
。
BOOL RunThread()
{
CloseHandle((HANDLE)_beginthreadex(NULL, NULL, ThreadProc, this, NULL, NULL));
CloseHandle((HANDLE)_beginthreadex(NULL, NULL, ThreadProc, this, NULL, NULL));
CloseHandle((HANDLE)_beginthreadex(NULL, NULL, ThreadProc, this, NULL, NULL));
CloseHandle((HANDLE)_beginthreadex(NULL, NULL, ThreadProc, this, NULL, NULL));
CloseHandle((HANDLE)_beginthreadex(NULL, NULL, ThreadProc, this, NULL, NULL));
return TRUE;
}
2、
运行结果
实际运行结果却令人意外,m_lInterlockedData = 11, why?
3、
原因
做以下假设:
3.1
当m_lInterlockedData = 9
时,线程1
运行完while(m_lInterlockedData < 10)
,会判断为真。
3.2
此时系统切换到线程2
运行,线程2
的Work
函数会将m_lInterlockedData
增加到10
。
3.3
系统再次切换返回到线程1
运行,由于while
的判定代码已执行且为真,所以此时会执行InterlockedIncrement(&m_lInterlockedData);
从而将m_lInterlockedData
再次增加到11
。
4、
解决方法
改用临界区即可解决如上问题
int WorkEx()
{
while (TRUE)
{
EnterCriticalSection(&m_cs);
if (m_lInterlockedData < 10)
{
m_lInterlockedData++;
LeaveCriticalSection(&m_cs);
}
else
{
LeaveCriticalSection(&m_cs);
break;
}
Sleep(100);
}
printf("CInterlocked::Work end\n");
return 0;
}
注意,为了不让在临近区中等待过久,故将Sleep(100) 放在LeaveCriticalSection() 之外。