互斥量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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Android实现自由单选、复选按钮效果+样式美化[通俗易懂]

    Android实现自由单选、复选按钮效果+样式美化[通俗易懂]背景Android开发中会遇到将单选按钮排布在多行的情况,一般只能通过自定义控件的形式,绘制单选按钮,网络上也有很多这样的文章,但一般情况下自定义的控件在界面美观性、效果方面稍有欠缺。因此,我们打算用CheckBox+LinearLayout来实现一种多行单选按钮组的效果。效果如下:思路Android中要实现单选按钮要用到RadioGroup+RadioButton的布局结…

    2022年5月13日
    42
  • 序列(两)密钥索引、桶排序、位图、失败者树(照片详细解释–失败者树)「建议收藏」

    序列(两)密钥索引、桶排序、位图、失败者树(照片详细解释–失败者树)「建议收藏」序列(两)以上排序算法都有一个性质:在排序的终于结果中,各元素的次序依赖于它们之间的比較。我们把这类排序算法称为比較排序。不论什么比較排序的时间复杂度的下界是nlgn。下面排序算法是用运算而不是比較来

    2022年7月1日
    24
  • springboot中logback配置(spring配置类)

    1、Logback简介Logback是由log4j创始人设计的又一个开源日志组件。相比于log4j,Logback重写了内核,在一些关键执行路径上性能提升10倍以上。而且logback不仅性能提升了,初始化内存加载也更小; logback当前分成三个模块:logback-core,logback-classic和logback-access。logback-core是其它两个…

    2022年4月11日
    50
  • 1.3家用路由器的使用

    1.3家用路由器的使用

    2021年8月24日
    44
  • DNS 负载均衡

    DNS 负载均衡DNS负载均衡技术的实现原理是在DNS服务器中为同一个主机名配置多个IP地址,在应答DNS查询时,DNS服务器对每个查询将以DNS文件中主机记录的IP地址按顺序返回不同的解析结果,将客户端的访问引导到不同的机器上去,使得不同的客户端访问不同的服务器,从而达到负载均衡的目的。 最早的负载均衡技术是通过DNS来实现的,在DNS中为多个地址配置同一个名字,因而查询这个名字的客户机将得到其中一个地…

    2022年7月14日
    13
  • navicat 15.0.17版本激活码_最新在线免费激活

    (navicat 15.0.17版本激活码)本文适用于JetBrains家族所有ide,包括IntelliJidea,phpstorm,webstorm,pycharm,datagrip等。https://javaforall.net/100143.htmlIntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,上面是详细链接哦~0…

    2022年3月28日
    153

发表回复

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

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