实验三:线程的互斥

2.3.1实验⽬的

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

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

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

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

2.3.2.1临界区对象

临界区对象(CriticalSection)包括初始化临界区(InitializeCriticalSection())、进⼊临界区

( EnterCriticalSection ())、退出临界区( LeaveCriticalSection ())及删除临界区

(DeleteCriticalSection())等API函数。

初始化临界区

InitializeCriticalSection()⽤于初始化临界区对象。

原型:

VOID InitializeCriticalSection(

LPCRITICAL_SECTION lpCriticalSection

);

参数说明:

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

返回值:

该函数没有返回值。

⽤法举例:

LPCRITCAL_SECTION hCriticalSection;

CRITICAL_SECTION Critical;

hCriticalSection=&Critical;

InitializeCriticalSection(hCriticalSection);

进⼊临界区

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

原型:

VOID EnterCriticalSection(

LPCRITICAL_SECTION lpCriticalSection

);

参数说明:

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

返回值:

该函数没有返回值。

⽤法举例:

LPCRITICAL_SECTION hCriticalSection;

CRITICAL_SECTION Critical;

hCriticalSection=&Critical;

EnterCriticalSection(hCriticalSection);

退出临界区

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

原型:

VOID LeaveCriticalSection(

LPCRITICAL_SECTION lpCriticalSection );

参数说明:

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

返回值:

该函数没有返回值

⽤法举例:

LPCRITICAL_SECTION hCriticalSection;

CRITICAL_SECTION Critical;

hCriticalSection=&Critical;

LeaveCriticalSection(hCriticalSection);

删除临界区

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

原型:

VOID DeleteCriticalSection(

LPCRITICAL_SECTION lpCriticalSection

);

参数说明:

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

返回值:

该函数没有返回值。

⽤法举例:

LPCRITICAL_SECTION hCriticalSection;

CRITICAL_SECTION Critical;

hCriticalSection=&Critical;

DeleteCriticalSection(hCriticalSection);

2.3.2.2互斥对象

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

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

创建互斥对象

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

原型:

HANDLE CreateMutex(

LPSECURITY_ATTRIBUTES lpMutexASributes,

BOOL bInitialOwner,

LPCTSTR lpName

);

参数说明:

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

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

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

值说明。

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

返回值:

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

原因。

⽤法举例:

static HANDLE hHandle1=NULL;

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

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

打开互斥对象

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

原型:

HANDLE OpenMutex(

DWORD dwDesiredAccess,

BOOL bInheritHandle,

LPCTSTR lpName

);

参数说明:

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

斥对象访问权。

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

表 2-4 对互斥对象的访问种类

访问 描述

MUTEX_ALL_ACCESS 可以进⾏对任何互斥对象的访问

SYNCHRONIZE 使⽤等待函数 wait functions 等待互斥对象成为可⽤状态或使⽤

ReleaseMutex()释放使⽤权,从⽽获得互斥对象的使⽤权

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

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

返回值

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

GetLastError()查询失败的原因。

⽤法举例:

static HANDLE hHandle1 = NULL;

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

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

  1. 释放互斥对象

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

原型:

BOOL ReleaseMutex(

HANDLE hMUTEX;

);

参数说明:

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

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

⽤法举例:

sta2c HANDLE hHandle1=NULL;

BOOL rc;

rc= ReleaseMutex(hHandle1)

2.3.3 实验内容

完成两个⼦线程之间的互斥。在主线程中使⽤系统调⽤ CreateThread()创建两个⼦线程,并使两个⼦

线程互斥的使⽤全局变量 count。

2.3.4 实验要求

能正确的使⽤临界区对象,包括初始化临界区 Ini2alizeCri2calSec2on()、进⼊临界区

EnterCri2calSec2on()、退出临界区 LeaveCri2cal()及删除临界区 DeleteCri2calSec2on() 进⼀步理解线程

的互斥。

2.3.5 实验指导

具体操作过程同实验⼀,在 Microsoa Visual C++ 6.0 环境下建⽴⼀个MFC⽀持的控制台⼯程⽂件,编

写C程序,在主线程中使⽤Ini2alizeCri2calSec2on()初始化临界区,然后建⽴两个⼦线程,在两个⼦线程

中使⽤全局变量 count 的前、后分别使⽤EnterCri2calSea2on()进⼊临界区LeaveCri2calSec2on()退出临

界区,等两个⼦线程运⾏完毕,主线程使⽤DeleteCri2calSec2on()删除临界区并撤销线程。

2.3.6 实验总结

该试验完成了两个⼦线程之间的互斥。若去掉互斥对象,观察全局变量count的变化,了解互斥对象

的作⽤,进⼀步理解线程的互斥。本试验也可以使⽤互斥对象(Mutex)来完成两个线程的互斥,互斥对

象(Mutex)的使⽤⽅法与信号量对象相似,这⾥不再说明,请同学⾃⼰完成。线程互斥访问全局变量

count

如图 2-5所示。

2.3.7 源程序

#include "stdafx.h"
#include <Windows.h>#ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[ ]=__FILE__; #endif ////The one and only applica2on 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); //退出临界区
}

2.3.8 实验展望

上⾯的实验是使⽤临界区对象(Cri2calSec2on)实现的,同学们可以使⽤互斥对象(Mutex)来完

成。

在完成以上三个实验后,同学们对Windows系统提供的线程创建与撤销、线程的同步与互斥、API有

了⼀定的了解,在此基础上设计并完成⼀个综合性的实验解决实际同步与互斥问题,如⽣产者与消费者问题、读者与写者问题等。饰演的题⽬可以⾃⾏设计,但要求必须涉及线程的创建与撤销、等待对象函

数(waitFunc2ons)、信号量对象(Semaphore)临界区对象(Cri2calSec2on)或互斥对象(Mutex)的使

⽤。

操作系统 实验三:线程的互斥相关推荐

  1. linux中关于ssh实验,操作系统实验三linux的telnetftpssh的相关配置及验证

    操作系统实验三linux的telnetftpssh的相关配置及验证 -1-昆明理工大学信息工程与自动化学院学生实验报告( 2010 -2011 学年第 二 学期 )课程名称:操作系统 开课实验室:信自 ...

  2. 操作系统实验三、进程通信

    文章目录 操作系统实验三.进程通信 一.实验目的 二.实验内容 三.设计原理(或方案)及相关算法 四.结果分析 五.源代码 操作系统实验三.进程通信 一.实验目的 ​ 1.了解和熟悉Linux支持的消 ...

  3. 操作系统实验三进程间通信

    文末也可直接获取实验文档 实验三 进程间通信 目录 1实验目的 2 实验内容 3实验详细操作步骤及程序清单: 4相关问题及思考 5总结 6背景知识 1实验目的 1.了解linux系统中进程通信的基本原 ...

  4. linux系统进程调度算法实验,操作系统实验三、进程调度算法实验

    实验三.进程调度算法实验 3.1 实验目的 加深对进程调度概念的理解,体验进程调度机制的功能,了解Linux 系统中进程 调度策略的使用方法.练习进程调度算法的编程和调试技术. 3.2 实验说明 在 ...

  5. 超详细!操作系统实验三 系统调用(哈工大李治军)

    实验3 系统调用 提醒 这次实验涉及的宏过于复杂,加上本人能力有限,我也没有花大量时间去研究每一段代码,只是理解到每一段代码做了什么这一程度. 实验目的 此次实验的基本内容是:在 Linux 0.11 ...

  6. 操作系统实验三:进程管理

    实验三 进程管理 一.实验要求 (1)掌握操作系统中进程的基本概念: (2)掌握 Linux操作系统进程管理基本方法: (3)了解进程并发运行的过程. 二.实验内容 (1)验证实验: ① 启动vi编辑 ...

  7. 操作系统 实验三 进程调度模拟程序

                                                          实验三 进程调度模拟程序                                   ...

  8. 操作系统实验三:主存空间的分配与回收

    实验三:主存空间的分配与回收 一.实验目的 通过本次实验,帮助学生理解在可变式分区管理方式下,如何实现主存空间的分配与回收. 二.实验内容 主存是中央处理机能直接存取指令和数据的存储器.能否合理而有效 ...

  9. 【操作系统】实验楼操作系统实验三——系统调用

    操作系统实验3--系统调用 环境配置 ​ 首先同样是配置环境 cd /home/shiyanlou/oslab tar -zxvf hit-oslab-linux-20110823.tar.gz -C ...

最新文章

  1. 如何在ubuntu下使用samba创建共享
  2. 使用CmakeLists应该知道的一些知识
  3. Sklearn参数详解—聚类算法
  4. jop怎么读音英语怎么说_“春晚”英语怎么说?
  5. python接口编程的好处_python接口自动化测试
  6. 微信小程序全面开放近一年,姗姗来迟的阿里还有胜局吗?| 畅言
  7. Atitit.分布式远程调用  rpc  rmi  CORBA的关系
  8. linux打包除了某个文件夹,tar打包且排除某个文件
  9. android脚本模拟器,android运行模拟器脚本(批处理)
  10. Android 查询局域网内所有ip和mac地址
  11. 51单片机 | 步进电机实验
  12. android(4) 使用ViewPaper 以及这几年来的一些感悟
  13. 算法题:最少出牌次数
  14. DxO PhotoLab 2.2.2完整精华汉化版|顶级RAW数码后期软件
  15. 局域网arp攻击_本地复现 ARP欺骗攻击
  16. 关于jquery的click()和trigger(‘click‘)方法的一点问题
  17. Kubernetes(四) - Pod和Deployment
  18. C300 简单配置
  19. python大规模获取豆瓣影评_Python 获取豆瓣用户电影收藏数据
  20. 隆重推荐:隐身专家V2.91下载!

热门文章

  1. 【STM32Cube笔记】11-中断控制器NVIC
  2. vimdiff比较两个文件
  3. Appender的几种实现方式
  4. android 实例 super 什么意思
  5. CSS样式层叠关系(一)-- 外部,内部与内联
  6. 在VMware中安装红帽Linux系统
  7. ue4-摄像机动画Matinee(多图慎入)
  8. XGRegressor参数设置
  9. Orcal数据库中ORA-01861: 文字与格式字符串不匹配
  10. python实现魔方复原_大佬们帮忙看一下,python解三阶魔方有沒有更快的方法