操作系统实验三、线程的互斥

实验三 线程的互斥

1.实验目的

(1) 熟练掌握Windows系统环境下线程的创建与撤销。

(2)熟悉Windows系统提供的线程互斥API。

(3)使用WIndows系统提供的线程互斥API解决实际问题。

2.实验准备知识:相关API函数介绍

临界区对象

​ 临界区对象(CriticalSection)包括初始化临界区(InitializeCriticalSection())、进入临界区(EnterCriticalSection())、退出临界区(LeaveCriticalSection())及删除临界区(DeleteCriticalSection())等API函数。

(1)初始化临界区

IntializeCriticalSection() 用于初始化临界区对象。

原型:

IntializeCriticalSection(

LPCRITICAL_SECTION IpCriticalSection

);

参数说明:

IpCriticalSection:指出临界区对象的地址。

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

**返回值:**无。

用法举例:

LPCRITICAL_SECTION hCriticalSection;

CRITICAL_SECTION Critical;

hCriticalSection=&Critical;

InitializeCriticalSection(hCriticalSection);

(2)进入临界区

EnterCriticalSection()等待进入临界区的权限,当获得该权限后进入临界区。

原型:

VOID EnterCriticalSection(

LPCRITICAL_SECTION IpCriticalSection

);

参数说明:

IpCriticalSection:指出临界区对象的地址。

**返回值:**无。

用法举例:

LPCRITICAL_SECTION hCriticalSection;

CRITICAL_SECTION Critical;

hCriticalSection=&Critical;

EnterCriticalSection(hCriticalSection);

(3)退出临界区

LeaveCriticalSection()释放临界区的使用权限。

原型:

VOID LeaveCriticalSection(

LPCRITICAL_SECTION IpCriticalSection

);

参数说明:

IpCriticalSection:指出临界区对象的地址。

**返回值:**无。

用法举例:

LPCRITICAL_SECTION hCri2calSec2on;

CRITICAL_SECTION Cri2cal;

hCri2calSec2on=&Cri2cal;

LeaveCri2calSec2on(hCri2calSec2on);

(4)删除临界区

DeleteCri2calSec2on()删除与临界区有关的所有系统资源。

原型:

VOID DeleteCri2calSec2on(

LPCRITICAL_SECTION lpCri2calSec2on

);

参数说明:

lpCri2calSec2on:指出临界区对象的地址。

返回值:

该函数没有返回值。

⽤法举例:

LPCRITICAL_SECTION hCri2calSec2on;

CRITICAL_SECTION Cri2cal;

hCri2calSec2on=&Cri2cal;

DeleteCri2calSec2on(hCri2calSec2on);

互斥对象

互斥对象(Mutex)包括创建互斥对象(CreateMutex())、打开互斥对象(OpenMutex())及释

放互斥对象(ReleaseMutex())API函数。

(1)创建互斥对象

CreateMutex(0⽤于创建⼀个互斥对象。

原型:

HANDLE CreateMutex(

LPSECURITY_ATTRIBUTES lpMutexASributes,

BOOL bIni2alOwner,

LPCTSTR lpName

);

参数说明:

lpMutexASributes:指定安全属性,为NULL时,信号量得到⼀个,默认的安全描述符。

bIni2alOwner:指定初始的互斥对象。如果该值为TRUE并且互斥对象已经纯在,则调⽤线程获得互斥

对象的所有权,否则调⽤线程不能获得互斥对象的所有权。想要知道互斥对象是否已经存在,参⻅返回

值说明。

lpName:给出互斥对象的名字。

返回值:

互斥对象创建成功,将返回该互斥对象的句柄。如果给出的互斥对象是系统已经存在的互斥对象,将返回这个已存在互斥对象的句柄。如果失败,系统返回NULL,可以调⽤函数GetLastError()查询失败的

原因。

⽤法举例:

sta2c HANDLE hHandle1=NULL;

//常⻅⼀个名为"MutexName1"的互斥对象

hHandle1=CreateMutex(NULL,FALSE, “MutexName1”);

(2)打开互斥对象

OpenMutex()⽤于打开⼀个互斥对象。

原型:

HANDLE OpenMutex(

DWORD dwDesiredAccess,

BOOL bInheritHandle,

LPCTSTR lpName

);

参数说明:

指明系统安全属性⽀持的对互斥对象所有可能的访问。如果系统安全属性不⽀持,则不能获得对互

斥对象访问权。

(1)dwDesireAccess:指出发开后要对互斥对象进⾏何种访问,具体描述如表所示。

对互斥对象的访问种类:

访问 描述
MUTEX_ALL_ACCESS 可以进⾏对任何互斥对象的访问
SYNCHRONIZE 使⽤等待函数 wait func2ons 等待互斥对象成为可⽤状态或使⽤ReleaseMutex()释放使⽤权,从⽽获得互斥对象的使⽤权

(2) bInheritHandle: 指出返回信号量的句柄是否可以继承。

(3) IpName : 给出信号量的名字。

返回值

互斥对象打开成功,将返回该互斥对象的句柄;如果失败,系统返回NULL,可以调⽤函数

GetLastError()查询失败的原因。

⽤法举例:

sta2c HANDLE hHandle1 = NULL;

//打开⼀个名为"MutexName1"的互斥对象

hHandle=OpenMutex(SYNCHRONIZE,NULL,“MutexName1”);

(3)释放互斥对象

ReleaseMutex() ⽤于释放互斥对象。

原型:

BOOL ReleaseMutex(

HANDLE hMUTEX;

);

参数说明:

hMutex:Mutex对象的句柄。CreateMutex()和OpenMutex()函数返回该句柄。

**返回值:**如果成功,将返回⼀个⾮0值;如果失败系统将返回0,可以调⽤函数 GetLastError()查询失败的原因。

⽤法举例:

sta2c HANDLE hHandle1=NULL;

BOOL rc;

rc= ReleaseMutex(hHandle1)

3.实验内容

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

#include "stdafx.h"
#include "1.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 int count =5; 
static HANDLE h1; 
static HANDLE h2; 
LPCRITICAL_SECTION hCriticalSection; //定义指向临界区对象的地址指针
CRITICAL_SECTION Critical; //定义临界区
void func1(); 
void func2(); 
int _tmain(int argc,TCHAR*argv[],TCHAR*envp[]) 
{
    
    
	int nRetCode=0; 
	DWORD dwThreadID1, dwThreadID2; 
	hCriticalSection=&Critical; //将指向临界区对象的指针指向临界区
	InitializeCriticalSection(hCriticalSection); //初始化临界区
	h1=CreateThread((LPSECURITY_ATTRIBUTES)NULL, 0, (LPTHREAD_START_ROUTINE)func1, (LPVOID)NULL, 0,&dwThreadID1); //创建线程 func1 
	if (h1==NULL) printf("Thread1 create FAIL!\n"); 
	else printf("Thread1 create Success!\n"); 
	h2=CreateThread((LPSECURITY_ATTRIBUTES)NULL, 0, (LPTHREAD_START_ROUTINE)func2, (LPVOID)NULL, 0,&dwThreadID2); //创建线程 func2 
	if (h2==NULL) printf("Thread2 create FAIL!\n"); 
	else printf("Thread2 create Success!\n");
	Sleep(1000); 
	CloseHandle(h1); 
	CloseHandle(h2); 
	DeleteCriticalSection(hCriticalSection); //删除临界区
	ExitThread(0); 
	return nRetCode; 
} 
void func2() 
{
    
     
	int r2; 
	EnterCriticalSection (hCriticalSection); //进入临界区
	r2=count; 
	Sleep(100); 
	r2=r2+1; 
	count=r2; 
	printf("count in func2=%d\n",count); 
	LeaveCriticalSection (hCriticalSection); //退出临界区
} 
void func1() 
{
    
     
	int r1; 
	EnterCriticalSection (hCriticalSection); //进入临界区
	r1=count; 
	Sleep(500); 
	r1=r1+1; 
	count=r1; 
	printf("count in func1=%d\n",count); 
	LeaveCriticalSection (hCriticalSection); //退出临界区
}

4.实验结果与总结

1

猜你喜欢

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