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() 之外。