互斥量Mutex的简单应用

互斥量Mutex的简单应用一、互斥量的简单介绍互斥量是一个内核对象,它用来确保一个线程独占一个资源的访问。互斥量与关键段的行为非常相似,并且互斥量可以用于不同进程中的线程互斥访问资源。使用互斥量Mutex主要将用到四个函数。下面是这些函数的原型和使用说明。1) CreateMutex函数功能:创建互斥量函数原型:HANDLECreateMutex(LPSECURITY_ATTRIBUTES…

大家好,又见面了,我是你们的朋友全栈君。

一、互斥量的简单介绍

互斥量是一个内核对象,它用来确保一个线程独占一个资源的访问。互斥量与关键段的行为非常相似,并且互斥量可以用于不同进程中的线程互斥访问资源。

使用互斥量Mutex主要将用到四个函数。下面是这些函数的原型和使用说明。

1) CreateMutex

函数功能:创建互斥量

函数原型:

HANDLE CreateMutex(
  LPSECURITY_ATTRIBUTES lpMutexAttributes,
  BOOL                  bInitialOwner,     
  LPCTSTR               lpName
);

函数说明:

第一个参数表示安全控制,一般直接传入NULL。

第二个参数用来确定互斥量的初始拥有者。如果传入TRUE表示互斥量对象内部会记录创建它的线程的线程ID号并将递归计数设置为1,由于该线程ID非零,所以互斥量处于未触发状态。如果传入FALSE,那么互斥量对象内部的线程ID号将设置为NULL,递归计数设置为0,这意味互斥量不为任何线程占用,处于触发状态。

第三个参数用来设置互斥量的名称,在多个进程中的线程就是通过名称来确保它们访问的是同一个互斥量。

函数返回值:

成功返回一个表示互斥量的句柄,失败返回NULL。

2)OpenMutex

函数功能:打开互斥量,相当于使用互斥量

函数原型:

HANDLE OpenMutex(
 DWORD       dwDesiredAccess,
 BOOL        bInheritHandle,
 LPCTSTR     lpName     //名称
);

函数说明:

第一个参数表示访问权限,对互斥量一般传入MUTEX_ALL_ACCESS。详细解释可以查看MSDN文档。

第二个参数表示互斥量句柄继承性,一般传入TRUE即可。

第三个参数表示名称。某一个进程中的线程创建互斥量后,其它进程中的线程就可以通过这个函数来找到这个互斥量。

函数返回值:

成功返回一个表示互斥量的句柄,失败返回NULL。

3)ReleaseMutex

函数功能:触发互斥量,相当于解除对互斥量的占用

函数原型:

BOOL ReleaseMutex(HANDLE hMutex);

函数返回值:

成功返回TRUE,失败返回FALSE

4)CloseHandle

函数功能:清理互斥量,即释放内核对象

函数原型:

BOOL CloseHandle(
HANDLE hObject
);

函数说明:

hObject :代表一个已打开对象handle。

函数返回值:

成功返回TRUE,失败返回FALSE,可以调用GetLastError()获知失败原因。

二、互斥量的示例使用

本文章将使用3个进程示例互斥量的使用,相当于互斥量阻止三个进程同时使用同一块内存。但在贴代码之前先简要说明一下WaitForSingleObject函数,该函数用于检测hHandle事件的信号状态。

WaitForSingleObject

函数功能:用来检测hHandle事件的信号状态,在某一线程中调用该函数时,线程暂时挂起,如果在挂起的dwMilliseconds毫秒内,线程所等待的对象变为有信号状态,则该函数立即返回;如果超时时间已经到达dwMilliseconds毫秒,但hHandle所指向的对象还没有变成有信号状态,函数照样返回。

函数原型:

DWORD WaitForSingleObject(
HANDLE hHandle,
DWORD dwMilliseconds
);

函数说明:

hHandle:对象句柄。可以指定一系列的对象,如Event、Job、Memory resource notification、Mutex、Process、Semaphore、Thread、Waitable timer等。

dwMilliseconds:定时时间间隔,单位为milliseconds(毫秒).如果指定一个非零值,函数处于等待状态直到hHandle标记的对象被触发,或者时间到了。如果dwMilliseconds为0,对象没有被触发信号,函数不会进入一个等待状态,它总是立即返回。如果dwMilliseconds为INFINITE,对象被触发信号后,函数才会返回。

函数返回值:

WAIT_ABANDONED 0x00000080:当hHandle为mutex时,如果拥有mutex的线程在结束时没有释放核心对象(通过调用ReleaseMutex函数释放)会引发此返回值。

WAIT_OBJECT_0 0x00000000 :指定的对象出有有信号状态

WAIT_TIMEOUT 0x00000102:等待超时

WAIT_FAILED 0xFFFFFFFF :出现错误,可通过GetLastError得到错误代码

以上,就是WaitForSingleObject函数的简要介绍。

接下来将介绍3个进程示例互斥量的使用:

进程1(创建互斥量):

#include <stdio.h>
#include <Windows.h>
const TCHAR MUTEX_NAME[] = L"Mutext_test";

int _tmain(int argc, _TCHAR* argv[])
{
	HANDLE hMutex = CreateMutex(NULL, TRUE, MUTEX_NAME);
	printf("互斥量已经创建,现在按任意键触发互斥量\n");
	getchar();
	ReleaseMutex(hMutex);
	printf("互斥量已经触发\n");
	CloseHandle(hMutex);
	return 0;
}

进程2(打开互斥量):

#include <stdio.h>

const TCHAR MUTEX_NAME[] = L"Mutext_test";

int _tmain(int argc, _TCHAR* argv[])
{
	HANDLE hMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, MUTEX_NAME);
	if (hMutex == NULL)
	{
		printf("打开互斥量失败\n");
		getchar();
		return 0;		
	}

	printf("等待中...\n");
	DWORD dwResult = WaitForSingleObject(hMutex, 200 * 1000);
	switch (dwResult)
	{
	case WAIT_ABANDONED:
		printf("拥有互斥量的进程意外终止\n");
		break;
	case WAIT_OBJECT_0:
		printf("已经收到信号\n");
		break;
	case WAIT_TIMEOUT:
		printf("信号未在规定时间内送到\n");
		break;
	default:
		break;
	}

    // PS:要在释放互斥量之前加个getchar函数,这样有助于观察进程3在等待使用互斥量状态
	getchar();
	ReleaseMutex(hMutex);
	CloseHandle(hMutex);
	return 0;
}

进程3(打开互斥量):

const TCHAR MUTEX_NAME[] = L"Mutext_test";

int _tmain(int argc, _TCHAR* argv[])
{
	HANDLE hMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, MUTEX_NAME);
	if (hMutex == NULL)
	{
		printf("打开互斥量失败\n");
		getchar();
		return -1;
	}

	printf("等待中...\n");
	DWORD nResult = WaitForSingleObject(hMutex, 20 * 10000);
	switch(nResult)
	{
	case WAIT_ABANDONED:
		printf("创建互斥量进程已被废弃\n");
		break;
	case WAIT_OBJECT_0:
		printf("成功接收到信号\n");
		break;
	case WAIT_TIMEOUT:
		printf("等待时间已超时\n");
		break;
	default:
		break;
	}
	getchar();
	ReleaseMutex(hMutex);
	CloseHandle(hMutex);
	return 0;
}

执行结果如下:

互斥量Mutex的简单应用

互斥量Mutex的简单应用

当testOpenMutex1.exe 成功接收到信号后按下任意键后就会解除对该互斥量的使用,从而使testOpenMutex.exe可以使用该互斥量。

互斥量Mutex的简单应用

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/153199.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 老电脑换Linux系统是否会更快,旧电脑不要装Windows!Bodhi Linux系统,小巧强悍,运行更流畅…

    老电脑换Linux系统是否会更快,旧电脑不要装Windows!Bodhi Linux系统,小巧强悍,运行更流畅…你的旧电脑安装win10还好吗?现在科技发展越来越快,尤其是电脑硬件的更新换代,然而大多数的人都不会因为新产品出来,就将自己才用了两三年的电脑换掉。但是,电脑用久了,终究会变慢,尤其是在Windows系统功能越来愈多,越来越大的情况下,我们还是需要换电脑!不过,你的旧电脑怎么办?卖掉?它的价格分分钟还不如废铁。扔掉?又不太舍得。真是如鸡肋一般,食之无味,弃之可惜!很多人都不知道的是,其实即使是5年…

    2022年6月4日
    107
  • 用Pandas 处理大数据的3种超级方法

    用Pandas 处理大数据的3种超级方法原文链接:3simplewaystohandlelargedatawithPandas作者|GeorgeSeif译者|jojoa易上手,文档丰富的Pandas已经成为时下最火的数据处理库。此外,Pandas数据处理能力也一流。其实无论你使用什么库,大量的数据处理起来往往回遇到新的挑战。数据处理时,往往会遇到没有足够内存(RAM)这个硬件问题。企业往往…

    2022年5月24日
    113
  • ROC及AUC计算方法及原理「建议收藏」

    ROC及AUC计算方法及原理「建议收藏」1.非均衡分类问题在大多数情况下不同类别的分类代价并不相等,即将样本分类为正例或反例的代价是不能相提并论的。例如在垃圾邮件过滤中,我们希望重要的邮件永远不要被误判为垃圾邮件,还有在癌症检测中,宁愿误判也不漏判。在这种情况下,仅仅使用分类错误率来度量是不充分的,这样的度量错误掩盖了样例如何被错分的事实。所以,在分类中,当某个类别的重要性高于其他类别时,可以使用Precison和Recall多个比…

    2022年5月13日
    49
  • iptables如何删除一条规则

    iptables如何删除一条规则

    2021年6月3日
    133
  • 第一个Java程序—HelloWorld[通俗易懂]

    第一个Java程序—HelloWorld[通俗易懂]工欲善其事必先利其器,在写第一个Java程序之前,需要安装JDK以及配置环境变量,具体步骤见Windows中配置Java环境变量。环境变量搭建完成了,是不是已经迫不及待想敲几行代码跑跑看?走起!1.在英文路径下创建一个记事本文件,命名为HelloWorld.java。这个文件是存放java代码的文件,称为源文件。这里是将文件类型改为java类型,并不单单是名字。这里的.java是文件类型,有的电脑上可能文件后缀名给隐藏了,虽然文件名里有.java但不是个java文件。可以点击查看,将文件扩展

    2022年7月9日
    17
  • Matlab中读取txt文件的几种方法[通俗易懂]

    Matlab中读取txt文件的几种方法[通俗易懂]matlab读取文本文件的几种函数:1、load——适合读取纯数据文本;2、importdata——只读取数据,自动省略数据格式前后的字符,超大文件不适合;3、textread、textscan——适合读取行列规整的文本,会存到元胞中,可通过headerlines省略读取字段名(字符行);4、csvread、dlmread——适合读取csv、xsl等文件格式文本;5、fprintf、fscanf—…

    2025年9月5日
    5

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号