windows多线程(五) 互斥量 Mutex
一、互斥量
互斥量是windows的一个内核对象,互斥量与关键段的作用相似,可以用来确保全局资源的互斥访问。并且互斥量可以用在不同的进程中的线程互斥访问全局资源。
二、相关函数说明
使用互斥量Mutex主要用到以下四个函数,下面将介绍这四个函数。
(一) 创建互斥量
1. 函数原型
HANDLE CreateMutex(
LPSECURITY_ATTRIBUTE SlpMutexAttributes,
BOOL bInitialOwner,
LPCTSTR lpName
);
2.参数说明
第一个参数表示安全控制,一般直接传入NULL。
第二个参数用来确定互斥量的初始拥有者。如果传入TRUE表示互斥量对象内部会记录创建它的线程的线程ID号并将递归计数设置为1,由于该线程ID非零,所以互斥量处于未触发状态。如果传入FALSE,那么互斥量对象内部的线程ID号将设置为NULL,递归计数设置为0,这意味互斥量不为任何线程占用,处于触发状态。
第三个参数用来设置互斥量的名称,在多个进程中的线程就是通过名称来确保它们访问的是同一个互斥量。
函数返回值:成功返回一个表示互斥量的句柄,失败返回NULL。
(二) 打开互斥量
1. 函数原型
HANDLE OpenMutex(
DWORD dwDesiredAccess,
BOOL bInheritHandle,
LPCTSTR lpName
);
2.参数说明
第一个参数表示
权限,对互斥量一般传入MUTEX_ALL_ACCESS。
第二个参数表示互斥量句柄继承性,一般传入TRUE即可。
第三个参数表示名称。某一个进程中的线程创建互斥量后,其它进程中的线程就可以通过这个函数来找到这个互斥量。
函数返回值:成功返回一个表示互斥量的句柄,失败返回NULL。
(三) 触发互斥量
1. 函数原型
BOOLReleaseMutex (HANDLEhMutex)
2.参数说明
传入参数为从创建或打开互斥量时返回的句柄。 访问互斥资源前应该要调用等待函数,结束访问时就要调用ReleaseMutex()来表示自己已经结束访问,其它线程可以开始访问了。
(四) 释放互斥量
由于互斥量是一个内核对象,释放时直接调用 CloseHandle(HANDLE hObject) 函数就可以了,所有内核对象都是这样释放。
三、实例
1.创建并使用互斥量
#include <stdio.h>
#include <windows.h>
const unsigned int THREAD_NUM = 15;
unsigned int g_Count = 0;
HANDLE g_Mutex; //声明一个内核对象
DWORD WINAPI ThreadFunc(LPVOID);
int main()
{
g_Mutex = CreateMutex(NULL,false,NULL); // 创建互斥量,初始化为触发状态
HANDLE hThread[THREAD_NUM];
for (int i = 0; i < THREAD_NUM; i++)
{
hThread[i] = CreateThread(NULL, 0, ThreadFunc, &i, 0, NULL); // 创建线程
}
WaitForMultipleObjects(THREAD_NUM, hThread, true, INFINITE); //一直等待,直到所有子线程全部返回
printf(" 总共 %d 个线程给 g_Count 的值加1,现在 g_Count = %d \n\n", THREAD_NUM, g_Count);
CloseHandle(g_Mutex); //释放互斥量
return 0;
}
DWORD WINAPI ThreadFunc(LPVOID p)
{
int ThreadNum = *(int *)p;
WaitForSingleObject(g_Mutex, INFINITE); //等待互斥量触发
printf(" 第 %d 个线程给全局资源 g_Count 的值加1,现在 g_Count = %d\n", ThreadNum, ++g_Count);
ReleaseMutex(g_Mutex); // 触发互斥量
return 0;
}
程序运行结果如下图:

上面的程序中使用互斥量实现了对全局资源的互斥访问,但是并没有按照我们所预料顺序每个线程依次给 g_Count 加一。这说明使用互斥量只是实现了全局资源的互斥访问,并没有实现线程的同步,有关线程同步,会在接下来的文章中学习。
2.打开其他程序创建的互斥量
创建互斥量的程序(CreateMutex.c):
#include <stdio.h>
#include <windows.h>
const char MutexName[] = "MyMutex"; //互斥量名字
int main()
{
HANDLE hMutex = CreateMutex(NULL, TRUE, MutexName); //创建互斥量并初始化为未触发状态
printf("互斥量已经创建,按任意键触发\n");
getch();
ReleaseMutex(hMutex); // 触发互斥量
printf("互斥量已经被触发\n");
CloseHandle(hMutex);
return 0;
}
使用互斥量的程序(OpenMutex.c):
#include <stdio.h>
#include <windows.h>
const char MutexName[] = "MyMutex"; //互斥量名字
int main()
{
HANDLE hMutex = OpenMutex(MUTEX_ALL_ACCESS, TRUE, MutexName); //打开互斥量
if (NULL != hMutex)
{
printf("打开互斥量成功,等待互斥量被触发\n");
WaitForSingleObject(hMutex, INFINITE); // 等待互斥量被触发
printf("互斥量已经被触发\n");
}
else
{
printf("打开互斥量失败。\n");
}
CloseHandle(hMutex);
return 0;
}
先运行第一个程序创建互斥量,输出 互斥量已经创建,按任意键触发 后,运行第二个程序,打开互斥量,打开互斥量后,在第一个程序窗口按任意键触发互斥量,两个窗口都会输出互斥量已经被触发。运行结果如下图:

关于互斥量的使用就先介绍到这儿,其实前面的关键段介绍和互斥量都还有很多内容没写到,我打算单独写一篇来分析他们两个的区别和共同点,这里就先不介绍了。
windows多线程(五) 互斥量 Mutex的更多相关文章
- windows多线程同步--互斥量
关于互斥量的基本概念:百度百科互斥量 推荐参考博客:秒杀多线程第七篇 经典线程同步 互斥量Mutex 注意:互斥量也是一个内核对象,它用来确保一个线程独占一个资源的访问.互斥量与关键段的行为非常相似, ...
- 多线程相关------互斥量Mutex
互斥量(Mutex) 互斥量是一个可以处于两态之一的变量:解锁和加锁.只有拥有互斥对象的线程才具有访问资源的权限.并且互斥量可以用于不同进程中的线程的互斥访问. 相关函数: CreateMutex用于 ...
- 总结windows多线程同步互斥
windows多线程同步互斥--总结 我的windows多线程系列文章: windows多线程--原子操作 windows多线程同步--事件 windows多线程同步--互斥量 windows多线程同 ...
- windows多线程同步互斥--总结
我的windows多线程系列文章: windows多线程--原子操作 windows多线程同步--事件 windows多线程同步--互斥量 windows多线程同步--临界区 windows多线程同步 ...
- windows多线程(六) 互斥量Mutex与关键段CriticalSection比较
一.关键段CS 和 互斥量Mutex 的相同点:都有线程拥有权 关键段和互斥量都有线程拥有权,即可以被一个线程拥有.在 前面讲关键段CS的文章中有说到,关键段结构体的第四个参数保存着拥有该关键段的线程 ...
- 转--- 秒杀多线程第七篇 经典线程同步 互斥量Mutex
阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇一个经典的多线程同步问题> <秒杀多线程第五篇经典线程同步关键段CS> <秒杀多线程第六篇经典线程同步事件Event& ...
- [一个经典的多线程同步问题]解决方案三:互斥量Mutex
本篇通过互斥量来解决线程的同步,学习其中的一些知识. 互斥量也是一个内核对象,它用来确保一个线程独占一个资源的访问.互斥量与关键段的行为非常相似,并且互斥量可以用于不同进程中的线程互斥访问资源.使用互 ...
- 多线程面试题系列(7):经典线程同步 互斥量Mutex
前面介绍了关键段CS.事件Event在经典线程同步问题中的使用.本篇介绍用互斥量Mutex来解决这个问题. 互斥量也是一个内核对象,它用来确保一个线程独占一个资源的访问.互斥量与关键段的行为非常相似, ...
- 秒杀多线程第七篇 经典线程同步 互斥量Mutex
本文转载于:http://blog.csdn.net/morewindows/article/details/7470936 前面介绍了关键段CS.事件Event在经典线程同步问题中的使用.本篇介绍用 ...
随机推荐
- ISP与IAP
ISP:in system program 顾名思义,在系统编程,单片机不用从电路上拆下,直接用下载器或者串口即可完成程序的烧写.这个是用于工程师调试程序,或者出厂时烧写程序.本质上是芯片出厂时烧录到 ...
- Codeforces 1155 D Beautiful Array DP,最大子段和
题意 给出一个长度为\(n\)的数列和数字\(x\),经过最多一次操作将数列的一个子段的每个元素变为\(a[i]*x\),使该数列的最大子段和最大 分析 将这个数列分为3段考虑,第一段和第三段是未修改 ...
- bzoj 前100题计划
bzoj前100题计划 xz布置的巨大的坑.. 有空填题解... 1002 轮状病毒 用python手动matrixtree打表. #include<bits/stdc++.h> #def ...
- MySQL5.7(二)数据库的基本操作
登录MySQL数据库 格式:mysql -u 用户名 -h 主机名或IP地址 -P 端口号 -p 密码
- TPO-23 C1 Post a student announcement
第 1 段 1.Listen to a conversation between a student and the director of campus activities. 请听一段学生与校园活 ...
- svn树冲突的解决方法
树冲突 就是开发人员移动.重命名.删除一个文件或文件夹,而另一名开发人员也对它们进行了移动.重命名.删除或者仅仅是修改时就会发生树冲突.有很多种不同的情形可以导致树冲突,而且不同的情形需要不同的步骤来 ...
- selenium 基本常用操作
from selenium import webdriverfrom selenium.webdriver.common.action_chains import ActionChains #鼠标操作 ...
- 2.5星|《AI进化论》:疑似基于PPT与公关稿整理汇编而成
AI进化论·解码人工智能商业场景与案例 全书是目前AI在一些热门领域的应用的介绍,包括各行业内AI可以实现的功能.现有相关公司的具体业务等.对各公司的介绍仅限于能实现什么业务,具体做的怎么样,有什么优 ...
- FFMS2 API 译文 [原创]
FFMS2 又称 FFmpegSource2,参阅 https://github.com/FFMS/ffms2. 原文:https://github.com/FFMS/ffms2/blob/maste ...
- 【机器学习】无监督学习Autoencoder和VAE
众所周知,机器学习的训练数据之所以非常昂贵,是因为需要大量人工标注数据. autoencoder可以输入数据和输出数据维度相同,这样测试数据匹配时和训练数据的输出端直接匹配,从而实现无监督训练的效果. ...