临界区

1、线程安全问题
每个线程都有自己的堆栈、这意味着不同的线程使用的变量是互相不影响的。
如果两个线程用的都是全局变量,那么两个线程都是使用的同一变量
 
多线程的线程安全问题
1、有全局变量
2、对全局变量有写的动作
那么我们就必须考虑线程安全问题
由此引出概念:一次只允许一个线程使用的资源称为临界资源,访问临界资源的代码程序称为临界区
 
如下面的程序是两个线程卖票的

#include <stdio.h>
#include <Windows.h>

int n = 10;
DWORD WINAPI ThreadProc(LPVOID lpParameter){
	while(n>0){
		printf("还有%d张票\n",n);
		Sleep(50);
		n--;
		printf("卖出一张,余票%d张\n",n);
	}
	return 0;
};
int main(int argc, char const *argv[])
{	
	HANDLE handle[2];
	//创建线程
	// HANDLE WINAPI CreateThread(
	//   _In_opt_   LPSECURITY_ATTRIBUTES lpThreadAttributes,
	//   _In_       SIZE_T dwStackSize,
	//   _In_       LPTHREAD_START_ROUTINE lpStartAddress,
	//   _In_opt_   LPVOID lpParameter,
	//   _In_       DWORD dwCreationFlags,
	//   _Out_opt_  LPDWORD lpThreadId
	// );

	handle[0] = CreateThread(NULL,0,ThreadProc,NULL,0,NULL);
	CloseHandle(handle[0]);
	handle[1] = CreateThread(NULL,0,ThreadProc,NULL,0,NULL);
	CloseHandle(handle[1]);

	getchar();
	return 0;
}

QQ20190221-155438@2x.png

 
2、解决问题
如果要保证对读写操作的全局变量是安全的,我们就需要构建一段临界区,可以自己实现,也可以使用windows api实现
 
 
3、临界区实现线程锁
<1> 创建临界区
CRITICAL_SECTION cs;
 
<2> 初始化全局变量
InitializeCriticalSection(&cs);
 
<3>实现临界区
EnterCriticalSection(&cs); //进入临界区
使用临界资源,对全局变量读写所有逻辑全放临界区里面
LeaveCriticalSection(&cs); //离开临界区
 
改善后的代码:
#include <stdio.h>
#include <Windows.h>

int n = 10;
CRITICAL_SECTION cs;

DWORD WINAPI ThreadProc(LPVOID lpParameter){
	EnterCriticalSection(&cs); //进入临界区
		while(n>0){
			printf("还有%d张票\n",n);
			n--;
			printf("卖出一张,余票%d张\n",n);
		}
	LeaveCriticalSection(&cs); //离开临界区 
	return 0;
};



int main(int argc, char const *argv[])
{	
	InitializeCriticalSection(&cs);
	HANDLE handle[2];
	//创建线程
	// HANDLE WINAPI CreateThread(
	//   _In_opt_   LPSECURITY_ATTRIBUTES lpThreadAttributes,
	//   _In_       SIZE_T dwStackSize,
	//   _In_       LPTHREAD_START_ROUTINE lpStartAddress,
	//   _In_opt_   LPVOID lpParameter,
	//   _In_       DWORD dwCreationFlags,
	//   _Out_opt_  LPDWORD lpThreadId
	// );

	handle[0] = CreateThread(NULL,0,ThreadProc,NULL,0,NULL);
	CloseHandle(handle[0]);
	handle[1] = CreateThread(NULL,0,ThreadProc,NULL,0,NULL);
	CloseHandle(handle[1]);

	getchar();
	return 0;
}

2x.png

 

本博客所有文章如无特别注明均为原创。作者:odaycaogen复制或转载请以超链接形式注明转自 123``blog
原文地址《临界区

相关推荐

发表评论

路人甲 表情
Ctrl+Enter快速提交

网友评论(0)