什么时候多线程会出现问题
DWORD a=0;
DWORD WINAPI ThpeadProc1(PVOID lpcharator)
{
DWORD i=0;
while (i<50000)
{
a++;
i++;
}
return 0;
}
DWORD WINAPI ThpeadProc2(PVOID lpcharator)
{
DWORD i=0;
while (i<50000)
{
a++;
i++;
}
return 0;
}
void main()
{
HANDLE hThread1= CreateThread(0,0,ThpeadProc1,0,0,0);
HANDLE hThread2= CreateThread(0,0,ThpeadProc2,0,0,0);
Sleep(1000);
printf("%d",a);
getchar();
}
创建两个线程,每一个线程对全局变量a实现+50000,如果正常的话结果应该是100000;
这是运行的结果。(数字太小可能会运行结果正确,大一点容易看出问题)。
问题就处在线程1得到全局变量a的值还未加的时候,线程2这时候也在访问得到a的值。
要解决这一问题可以使用临界区
临界区
使用临界区先要初始化它
InitializeCriticalSection(
LPCRITICAL_SECTION lpCriticalSection
);
然后使用
EnterCriticalSection( LPCRITICAL_SECTION lpCriticalSection);
//在这里加入对全局变量操作的代码
LeaveCriticalSection( LPCRITICAL_SECTION lpCriticalSection);
在最后删除临界区
DeleteCriticalSection(LPCRITICAL_SECTION lpCriticalSection);
总结:当两个线程访问同一个全局的资源时,就可能会出现线程的安全问题。
EnterCriticalSection 这个函数相当于得到一个访问的令牌,只有拿到这个访问令牌才能执行后面的代码。这个令牌在同一时刻最多只能被一个线程拿到,其他线程必须等待拿到令牌的线程归还令牌(LeaveCriticalSection),不然是不能执行临界区中的代码。因为临界区中的代码应该尽量的不要占用太多的CPU时间,让别的线程一直阻塞。
最后贴上一个简单的临界区使用的代码
DWORD a=0;
DWORD WINAPI ThpeadProc1(PVOID lpcharator)
{
DWORD i=0;
while (i<50000)
{
EnterCriticalSection((LPCRITICAL_SECTION)lpcharator);//在这里进入临界区
a++;
LeaveCriticalSection((LPCRITICAL_SECTION)lpcharator);
i++;
}
return 0;
}
DWORD WINAPI ThpeadProc2(PVOID lpcharator)
{
DWORD i=0;
while (i<50000)
{
EnterCriticalSection((LPCRITICAL_SECTION)lpcharator);//在这里进入临界区
a++;
LeaveCriticalSection((LPCRITICAL_SECTION)lpcharator);
i++;
}
return 0;
}
void main()
{
CRITICAL_SECTION cs;
InitializeCriticalSection(&cs);
HANDLE hThread1= CreateThread(0,0,ThpeadProc1,&cs,0,0);
HANDLE hThread2= CreateThread(0,0,ThpeadProc2,&cs,0,0);
Sleep(4000);
printf("%d",a);
DeleteCriticalSection(&cs);
getchar();
}