操作系统实验二、线程的同步

实验二 线程的同步

一、实验目的

进一步掌握Windows系统环境下线程的创建和撤销;

熟悉Windows系统提供的线程同步API(是Windows提供给应用程序与操作系统的接口)

二、实验准备知识

1.进程的同步:

进程同步机制的主要任务,是对多个相关进程在执行次序上进行协调,使并发执行的诸进程之间能按照一定的规则(或时序)共享系统资源,并能很好地相互合作,从而使程序执行具有可再现性。

2.线程与进程的区别

由于线程具有许多传统进程所具有的特征,所以又称之为轻型进程或进程元,相应地,把传统进程称为重型进程。它相当于只有一个线程的任务。线程是比进程更小的基本单位。

3.线程同步中的“同步”

不是指线程的同步运行,而是指协同步调。协同步调就是按照预定的先后次序进行运行。比如,一人说完另一人再说。

4.相关API函数介绍

1)等待1个对象

WaitForSingleObject() 在指定时间内等待一个对象

DWORD WaitForSingleObject(
    HANDLE hHandle,//对象句柄
    DWORD dwMilliseconds //等待时间
)

2)等待多个对象

WaitForMultipleObjects() 在指定时间内等待多个对象

DWORD WaitForMultipleObjects(
	DWORD nCount,             //句柄数组中的句柄数
	const HANDLE *lpHAndles,  //指向对象句柄数组的指针
	BOOL fWaitAll,            //等待类型
	DWORD dwMilliseconds      //等待时间
)
3)可等待的对象列表

①change notification:变化通知

②console input:控制台输入

③Event:事件

④job:作业

⑤mutex:互斥信号量

⑥Process:进程

⑦semaphore:计数信号量

⑧thread:线程

⑨wait-able timer:定时器

三、实验内容

(一)实验情景1

在主线程中创建一个子线程:

子线程:用于制作麻辣香锅,制作用时5秒

主线程:等待子线程执行完毕,打印“开始食用香锅!”

如何等待一个对象:需要设定一个信号量,用于再主子线程之间相互告知运行状态

步骤

1)创建一个信号量:

hHandle1 = CreateSemaphore(NULL,0,1,"SemaphoreName1");

参数依次表示:安全标志符(为NULL表示默认的安全描述符),信号量的初始态,信号量的最大值,信号量的名称

2)打开一个信号量

hHandle1 = OpenSemaphore(SYNCHRONIZE|SEMAPHORE_MODIFY_STATE,NULL,"SemaphoreName1");

参数依次表示:访问标志(指出打开后要对信号量进行何种访问),继承标志(指出返回的信号量是否可以继承),信号量名

3)释放信号量

rc = ReleaseSemaphore(hHandle1,1,NULL);

参数依次表示:信号量对象句柄(创建或打开信号量时给出的信号量对象句柄),信号量要增加数值(信号量要增加数值),信号量要增加的数值地址(32位的一个变量)

4)等待单个对象

dRes = WaitForSingleObject(hHandle1,INFINITE);

参数依次表示:信号量的句柄,INFINITE指的是如果信号量如果信号量没有释放将无限期的释放下去

5)等待多个对象

dRes = WaitForMultipleObjects(3,hHandles,1,INFINITE);

参数依次表示:等待对象的个数,等待多个对象数组的指针,第三个参数为1或true时就要等待数组当中所有的对象,INFINITE指的是如果信号量如果信号量没有释放将无限期的释放下去

// 01.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "01.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/
// The one and only application object

CWinApp theApp;

using namespace std;
static HANDLE hHandle1=NULL;
void chef(){
	printf("麻辣香锅开始制作,预计等待时间5秒。\n");
	Sleep(5000);
	printf("麻辣香锅制作完成!");

	BOOL rc;
	DWORD err;
	 rc = ReleaseSemaphore(hHandle1,1,NULL);
	 err=GetLastError();
	 printf("ReleaseSemaphore err=%d\n",err);
	 if(rc==0){
		 printf("Semaphore Release Fail!rc=%d\n",rc);

	 }
	 else{
		 printf("Semaphore Release Success!rc=%d\n",rc);
	 }
}
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
	int nRetCode = 0;
	DWORD dRes,err;

	hHandle1 = CreateSemaphore(NULL,0,1,"SemaphoreName1");
	if (hHandle1==NULL)printf("Semaphore Create Fail!\n");
	else printf("Semaphore Create Success!\n");
    


	hHandle1=OpenSemaphore(SYNCHRONIZE|SEMAPHORE_MODIFY_STATE,NULL,"SemaphoreName1");                               //打开信号量
	if (hHandle1==NULL)  printf("Semaphore Open Fail!\n");
	else printf("Semaphore Open Success!\n");



	HANDLE handle1=NULL;
	DWORD ThreadID1=NULL;
	handle1=CreateThread((LPSECURITY_ATTRIBUTES)NULL,0,(LPTHREAD_START_ROUTINE) chef,(LPVOID)NULL,0,&ThreadID1);                                 //创建子线程

	dRes=WaitForSingleObject(hHandle1,INFINITE);        //主线程等待子线程结束
	err=GetLastError();


	if(err==0){
		printf("麻辣香锅上菜完毕,请开动吧。\n");
	}
	else{
		printf("WaitForSingleObject err=%d\n",err);
		if(dRes==WAIT_OBJECT_0) printf("TIMEOUT!dRes=%d\n",dRes);
		else if(dRes==WAIT_OBJECT_0) printf("WAIT_OBJECT!dRes=%d\n",dRes);
		else if(dRes==WAIT_ABANDONED) printf("WAIT_ABANDONED!dRes=%d\n",dRes);
		else printf("dRes=%d\n",dRes);
	}
	
	
	return 0;
}

2)实验情景2

void chef(int meal_code){
	if(meal_code==0)
	{
		Sleep(5000);
		printf("麻辣香锅制作完成!\n");
	}
	else if(meal_code==1)
	{
		Sleep(3000);
		printf("什锦菇制作完成!\n");
	}
	else if(meal_code==2)
	{
		Sleep(6000);
		printf("米饭制作完成!\n");
	}
	
}
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
	int nRetCode = 0;
	DWORD dRes,err;

	HANDLE handle1=NULL;
	HANDLE handle2=NULL;
	HANDLE handle3=NULL;

	DWORD ThreadID1=NULL;
	DWORD ThreadID2=NULL;
	DWORD ThreadID3=NULL;

	int a=0;
	int b=1;
	int c=2;
	
	handle1=CreateThread((LPSECURITY_ATTRIBUTES)NULL,0,(LPTHREAD_START_ROUTINE) chef,(LPVOID)a,0,&ThreadID1);  
	handle2=CreateThread((LPSECURITY_ATTRIBUTES)NULL,0,(LPTHREAD_START_ROUTINE) chef,(LPVOID)b,0,&ThreadID2);
	handle3=CreateThread((LPSECURITY_ATTRIBUTES)NULL,0,(LPTHREAD_START_ROUTINE) chef,(LPVOID)c,0,&ThreadID3);

	HANDLE hHandles[3];
	hHandles[0]=handle1;
	hHandles[1]=handle2;
	hHandles[2]=handle3;
	dRes = WaitForMultipleObjects(3,hHandles,1,INFINITE);

	err=GetLastError();
	if(err==0){
		printf("所有的餐点已经上齐,请开动吧。\n");
	}
	else{
		printf("WaitForMultipleObjects err = %d\n",err);
		if(dRes==WAIT_TIMEOUT) printf("TIMEOUT!dRes=%d\n",dRes);
		else if(dRes==WAIT_OBJECT_0) printf("WAIT_OBJECT!dRes=%d\n",dRes);
		else if(dRes==WAIT_ABANDONED) printf("WAIT_ABANDONED!dRes=%d\n",dRes);
		else printf("dRes=%d\n",dRes);
	}
	return 0;
}

四、实验结果与总结

在主线程中创建一个子线程:

子线程:用于制作麻辣香锅,制作用时5秒

主线程:等待子线程执行完毕,打印“开始食用香锅!”

如何等待一个对象:需要设定一个信号量,用于再主子线程之间相互告知运行状态

1

2

线程同步中的“同步”

不是指线程的同步运行,而是指协同步调。协同步调就是按照预定的先后次序进行运行。比如,一人说完另一人再说。

猜你喜欢

转载自blog.csdn.net/weixin_44775375/article/details/107754876
今日推荐