互斥量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的简单应用

 

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

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

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 网络编程——UDP编程

    网络编程——UDP编程一、网络编程基础1.常用协议:IP协议;TCP协议;UDP协议;2.什么是Socket?二、服务器端的代码实现三、客户端的代码实现1.区别2.易混淆知识点四.代码实现五.最后小结

  • CloseableHttpClient发送http请求

    Stringresponse=null;//客户端接口请求路径Stringurl=EspConfig.getClientBaseUrl()+ClientUtil.CLIENT_METHODNAME;//创建请求CloseableHttpClienthttpclient=HttpClientBuilder.create().build();HttpPostpos…

  • 谷歌学术介绍_谷歌学术镜像官网

    谷歌学术介绍_谷歌学术镜像官网转载自:http://blog.renren.com/share/111541487/15517062888“谷歌学术”是谷歌搜索引擎中的学术检索部分,相对于知网、维普、万方、Pubmed等专业的论文数据库来说功能单薄了些,但具有页面简约、搜索速度快、集国内外文献于一体、某些文章可直接免费下载等优点,对忙于“赶制”毕业论文的广大同学们来说的确是一个不可多得的网站!

    2022年10月11日
  • 屏蔽自动更新描述文件(屏蔽描述文件)

    是不是应该说终于,是的。关于iOS屏蔽系统升级的描述文件在几个月前失效的事情大家都清楚了,苹果先是让描述文件失效,然后重新分享的屏蔽升级描述文件也相继的失效,之后也没有新的文件出来。之后是各种的sao操作出来,曲线饶了远路才能把iPhone晚上充电连着WIFI会自动升级的问题解决。有些方法还不能够完全解决问题,进行了屏蔽之后可能会让AppStore不能够进行正常的软件更新。之前修改WIFI,屏…

  • RecyclerView Adapter中notifyDataSetChanged 的作用

    RecyclerView Adapter中notifyDataSetChanged 的作用一直认为notifyDataSetChanged是用来刷新数据的当数据发生变化的时候调用notifyDataSetChanged官方说:通知任何注册的观察者数据发生了改变(Notifyanyregisteredobserversthatthedatasethaschanged)–自己翻译的不保证完全正确。。。。。。今天有空翻阅下源码publicfin…

  • ajax常见的面试问题[通俗易懂]

    ajax常见的面试问题[通俗易懂]1:什么是ajax?ajax作用是什么?异步的javascript和xmlAJAX是一种用于创建快速动态网页的技术。ajax用来与后台交互2:原生jsajax请求有几个步骤?分别是什么//创建XMLHttpRequest对象varajax=newXMLHttpRequest();//规定请求的类型、URL以及是否异步处理请求。ajax…

发表回复

您的电子邮箱地址不会被公开。

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