线程锁&&互斥体&&事件(处理临界区)

线程锁

临界区实现之线程锁:

创建全局变量:

CRITICAL_SECTION	cs;

初始化全局变量:

InitializeCriticalSection(&cs);

实现临界区:

EnterCriticalSection(&cs);
//使用临界资源
LeaveCriticalSection(&cs);

实例

#include <iostream>
#include<Windows.h>

//创建全局变量
CRITICAL_SECTION cs;
int a = 10;



void MyFirstThreadProc() {
    
    
	EnterCriticalSection(&cs);
	while (a > 0) {
    
    
		a--;
		printf("卖了一张,还有%d张票\n", a);
	}
	LeaveCriticalSection(&cs);


}

void MySecondThreadProc() {
    
    
	EnterCriticalSection(&cs);
	while (a > 0) {
    
    
		a--;
		printf("卖了一张,还有%d张票\n", a);
	}
	LeaveCriticalSection(&cs);

}
int main()
{
    
    
	//初始化全局变量
	InitializeCriticalSection(&cs);

	HANDLE aThreadProc[2];


	aThreadProc[1] = CreateThread(
		NULL,
		0,
		(LPTHREAD_START_ROUTINE)MyFirstThreadProc,
		NULL,
		0,
		NULL
	);

	aThreadProc[2] = CreateThread(
		NULL,
		0,
		(LPTHREAD_START_ROUTINE)MySecondThreadProc,
		NULL,
		0,
		NULL
	);

	system("pause");
	return 0;
}


在这里插入图片描述

总结:

  1. 线程锁只能用于单个进程间的线程控制
  2. 线程锁情况中,如果一个线程意外终结,但是并没有释放令牌,那么就出现无限等待情况。

互斥体

临界区实现之互斥体:

跨进程的临界资源访问:

HANDLE  CreateMutex()

创建一个互斥体(内核对象)

HANDLE g_hMutex=CreateMutex(NULL,FALSE,“xyz”)

“xyz”:互斥体的名字

FALSE:FALSE 的话就是信号(即可以直接使用);
TRUE 的话就是无信号(即不可以直接使用)(填TRUE的话,代表当前
这个互斥体属于当前这个进程

//有两种情况是可以获取令牌 1.有信号 2.线程拥有者

扫描二维码关注公众号,回复: 12581103 查看本文章

获取令牌:

WaitForSingleObject(g_hMutex,INFINITE)

释放令牌:

ReleaseMutex(g_hMutex)

同一个进程

#include <iostream>
#include<Windows.h>

int a = 10;

void MyFirstThreadProc() {
    
    

	//创建一个互斥体
	HANDLE g_hMutex = CreateMutex(NULL, TRUE, "xy");

	//获取令牌
	WaitForSingleObject(g_hMutex, INFINITE);
	while (a > 0) {
    
    
		a--;
		printf("A进程的x线程卖了一张,还有%d张票\n", a);
	}

	//释放令牌
	ReleaseMutex(g_hMutex);

}

void MySecondThreadProc() {
    
    
	//创建一个互斥体
	HANDLE g_hMutex = CreateMutex(NULL, TRUE, "xy");

	//获取令牌
	WaitForSingleObject(g_hMutex, INFINITE);
	while (a > 0) {
    
    
		a--;
		printf("B进程的y线程卖了一张,还有%d张票\n", a);
	}

	//释放令牌
	ReleaseMutex(g_hMutex);

}
int main()
{
    
    
	HANDLE aThreadProc[2];


	aThreadProc[1] = CreateThread(
		NULL,
		0,
		(LPTHREAD_START_ROUTINE)MyFirstThreadProc,
		NULL,
		0,
		NULL
	);

	aThreadProc[2] = CreateThread(
		NULL,
		0,
		(LPTHREAD_START_ROUTINE)MySecondThreadProc,
		NULL,
		0,
		NULL
	);

	system("pause");
	return 0;
}


在这里插入图片描述

在这里插入图片描述

不同进程

进程1(其实我也就加了一个getchar):

#include <iostream>
#include<Windows.h>

int a = 10;

void MyFirstThreadProc() {
    
    

	//创建一个互斥体
	HANDLE g_hMutex = CreateMutex(NULL, TRUE, "xy");

	//获取令牌
	WaitForSingleObject(g_hMutex, INFINITE);
	while (a > 0) {
    
    
		a--;
		printf("A进程的x线程卖了一张,还有%d张票\n", a);
	}

	getchar();
	//释放令牌
	ReleaseMutex(g_hMutex);

}

void MySecondThreadProc() {
    
    
	//创建一个互斥体
	HANDLE g_hMutex = CreateMutex(NULL, TRUE, "xy");

	//获取令牌
	WaitForSingleObject(g_hMutex, INFINITE);
	while (a > 0) {
    
    
		a--;
		printf("B进程的y线程卖了一张,还有%d张票\n", a);
	}
	getchar();
	//释放令牌
	ReleaseMutex(g_hMutex);

}
int main()
{
    
    
	HANDLE aThreadProc[2];


	aThreadProc[1] = CreateThread(
		NULL,
		0,
		(LPTHREAD_START_ROUTINE)MyFirstThreadProc,
		NULL,
		0,
		NULL
	);

	aThreadProc[2] = CreateThread(
		NULL,
		0,
		(LPTHREAD_START_ROUTINE)MySecondThreadProc,
		NULL,
		0,
		NULL
	);

	system("pause");
	return 0;
}


进程2:

#include <iostream>
#include<Windows.h>

int a = 10;

void MyFirstThreadProc() {
    
    

	//创建一个互斥体
	HANDLE g_hMutex = CreateMutex(NULL, FALSE, "xy");

	//获取令牌
	WaitForSingleObject(g_hMutex, INFINITE);
	while (a > 0) {
    
    
		a--;
		printf("B进程的x线程卖了一张,还有%d张票\n", a);
	}

	//释放令牌
	ReleaseMutex(g_hMutex);

}

void MySecondThreadProc() {
    
    
	//创建一个互斥体
	HANDLE g_hMutex = CreateMutex(NULL, FALSE, "xy");

	//获取令牌
	WaitForSingleObject(g_hMutex, INFINITE);
	while (a > 0) {
    
    
		a--;
		printf("B进程的y线程卖了一张,还有%d张票\n", a);
	}

	//释放令牌
	ReleaseMutex(g_hMutex);

}
int main()
{
    
    
	HANDLE aThreadProc[2];


	aThreadProc[1] = CreateThread(
		NULL,
		0,
		(LPTHREAD_START_ROUTINE)MyFirstThreadProc,
		NULL,
		0,
		NULL
	);

	aThreadProc[2] = CreateThread(
		NULL,
		0,
		(LPTHREAD_START_ROUTINE)MySecondThreadProc,
		NULL,
		0,
		NULL
	);

	system("pause");
	return 0;
}

在这里插入图片描述
互斥体1进程执行完了,但是互斥体1还没释放锁,因此互斥体2是不可能执行的,接下来我在互斥体1中按下回车键
在这里插入图片描述

CreateMutex返回值:

  1. 当前函数成功的话,那么返回值是一个互斥体的句柄
  2. 如果内核中同名互斥体已经存在了,那么CreateMutex这个函数也会返回一个句柄,返回值恰好就是原来按个互斥体的句柄。(但是此时GetlastError返回值是ERROR_ALREADY_EXISTS)
  3. 函数执行失败的话,返回值就是空

互斥体与线程锁的区别:

  1. 线程锁只能用于单个进程间的线程控制
  2. 互斥体可以设置等待超时,但线程锁不能
  3. 线程意外终结时,Mutex可以避免无限等待;线程锁情况中,如果一个线程意外终结,但是并没有释放令牌,那么就出现无限等待情况。
  4. Mutex效率没有线程锁高

事件

1.通知类型:

HANDLE	CreatEvent(
LPSECURITY_ATTRIBUTES	IpEventAttributes,					//SD
BOOL	bManualReset,								//reset	type
BOOL	bInitialState,									//initial	state
LPCTSTR	IpName									//object	name;

bManualReset是否是通知类型

bInitialState是否有信号
有信号的话,就可以使用WaitForSingleObject得到它;否则的话调用WaitForSingleObject时会一直处于等待状态(FALSE代表没有初始信号)

#include <iostream>
#include<Windows.h>

int a = 10;
HANDLE g_event;

void MyFirstThreadProc() {
    
    

	SetEvent(g_event);//设置事件为已通知
	WaitForSingleObject(g_event, INFINITE);
	while (a > 0) {
    
    
		a--;
		printf("B进程的x线程卖了一张,还有%d张票\n", a);

	}


}

void MySecondThreadProc() {
    
    	

	WaitForSingleObject(g_event, INFINITE);
	while (a > 0) {
    
    
	
		a--;
		printf("B进程的y线程卖了一张,还有%d张票\n", a);
	}


}
int main()
{
    
    
	 g_event = CreateEvent(NULL, FALSE, FALSE, NULL);
	 //第二个参数FALSE表示是否是通知类型,何为通知类型呢?也就是群发,A收到后,不会被改变它的状态;如果不是通知类型的话,那么A
	 //收到之后就会改变它的状态,然后B执行WaitForSingleObject不能成功。

	 //第三个参数表示是否有信号,TRUE为有信号,FALSE为无信号
	HANDLE aThreadProc[2];


	aThreadProc[1] = CreateThread(
		NULL,
		0,
		(LPTHREAD_START_ROUTINE)MyFirstThreadProc,
		NULL,
		0,
		NULL
	);

	aThreadProc[2] = CreateThread(
		NULL,
		0,
		(LPTHREAD_START_ROUTINE)MySecondThreadProc,
		NULL,
		0,
		NULL
	);

//	SetEvent(g_event);//设置事件为已通知


	system("pause");

	return 0;
}


在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/CSNN2019/article/details/113903759
今日推荐