多线程的安全问题

什么时候多线程会出现问题

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();
}

猜你喜欢

转载自blog.csdn.net/qq_41490873/article/details/86767301