多线程 - 临界区

多线程的同步和异步

 

异步: 例如赛跑,各跑各的。

同步: 例如接力赛,必须接班后才能跑(一个线程必须等到另一个线程的信号等)

互斥: 例如独木桥,一次只能过一个(线程)

 

在WIN32中同步机制主要有以下几种:

(1)临界区(Critical Section)

(2)信号量(Senaphore)

(3)互斥量(Mutex)

(4)事件(Event)

 

用户模式下的方法有:

1.原子操作,临界区。

2.通过对多线程的串行化来访问公共资源或一段代码,速度快,色和控制数据访问。

 

内核模式下的方法有:

1.互斥量:为协调共同对一个共享资源的单独访问而设计。

2.信号量:为控制一个具有有限数量用户资源而设计。

3.事件:用来统治线程有一些事件已发生,从而启动后继任务的开始。

 

 

临界区结构对象

CRITICAL_SECTION Section;

 

备注:(人工无法干预)

1.临界区在使用时以CRITICAL_SECTION结构对象保护共享资源。

2.如果有多个线程试图同时访问临界区,那么在有一个线程进入后,其他试图访问此临界区的线程将被挂起,并一直持续到进入临界区的线程离开。

3.临界区在被释放后,其他线程可以继续抢占,并一次达到用原子方式操作共享资源的目的。

 

初始化临界区

InitializeCriticalSection(&Section);

 

进入临界区(线程内)

EnterCriticalSection(&Section);

 

离开临界区(线程内)

LeaveCriticalSection(&Section);

 

尝试进入临界区(线程内)

TryEnterCriticalSection(&Section);       多用于if语句内  

返回:

成功:TRUE

失败 : FALSE

 

备注:(EnterCriticalSection 和 TryEnterCriticalSection)

EnterCriticalSection:

1.如果EnterCriticalSection的代码已经被占用,会使调用线程置于阻塞状态。

2.处于阻塞状态,那么该线程可能很长时间内不能被调度。

 

TryEnterCriticalSection:

1.TryEnterCriticalSection函数决不允许调用线程进入等待状态。

2.它的返回值能够指明调用线程是否能够获得对资源的访问权。

3.TryEnterCriticalSection 发现该资源已经被另个线程访问,它返回FALSE,否则TRUE。

4.运用这个函数,线程能够迅速查看它是否可以访问某个共享资源,如果不能访问,那么它可以继续执行某些其他操作,而不必进行等待。

 

删除临界区

DeleteCriticalSection(&Section);

 

#include<process.h>
#include<windows.h>
#include<iostream>

using namespace std;
int tickets = 100;
//1.创建临界区
CRITICAL_SECTION section;

void ThreadFun1(void*p);
void ThreadFun2(void*p);
int main()
{
	//2.初始化临界区
	InitializeCriticalSection(&section);
	cout << "开始!" << endl;
	HANDLE hThread1 = (HANDLE)_beginthread(ThreadFun1, 0, "窗口A");
	HANDLE hThread2 = (HANDLE)_beginthread(ThreadFun2, 0, "窗口B");
	HANDLE hArry[] = { hThread1,hThread2 };
	WaitForMultipleObjects(2, hArry, true, INFINITE);
	cout << "结束!" << endl;
	//5.删除临界区
	DeleteCriticalSection(&section);
	system("pause");
	return 0;
}

void ThreadFun1(void * p)
{
	char * name = (char*)p;
	cout << name << "开始售票" << endl;

	while (tickets > 0)
	{
		//3.进入临界区
		//EnterCriticalSection(&section);
		//3.尝试进入,与上一样 只是不会阻塞
		if (TryEnterCriticalSection(&section))
		{
			if (tickets > 0)
				printf("%s窗口卖出第%d张票!\n", name, tickets--);
			//4.离开临界区
			LeaveCriticalSection(&section);
		}
	}
}
void ThreadFun2(void * p)
{
	char * name = (char*)p;
	cout << name << "开始售票" << endl;

	while (tickets > 0)
	{
		//3.进入临界区
		EnterCriticalSection(&section);
		if (tickets > 0)
			printf("%s窗口卖出第%d张票!\n", name, tickets--);
		//4.离开临界区
		LeaveCriticalSection(&section);
	}
}

 

内容均为学习笔记

阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页