一、互斥量

互斥量是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的更多相关文章

  1. windows多线程同步--互斥量

    关于互斥量的基本概念:百度百科互斥量 推荐参考博客:秒杀多线程第七篇 经典线程同步 互斥量Mutex 注意:互斥量也是一个内核对象,它用来确保一个线程独占一个资源的访问.互斥量与关键段的行为非常相似, ...

  2. 多线程相关------互斥量Mutex

    互斥量(Mutex) 互斥量是一个可以处于两态之一的变量:解锁和加锁.只有拥有互斥对象的线程才具有访问资源的权限.并且互斥量可以用于不同进程中的线程的互斥访问. 相关函数: CreateMutex用于 ...

  3. 总结windows多线程同步互斥

    windows多线程同步互斥--总结 我的windows多线程系列文章: windows多线程--原子操作 windows多线程同步--事件 windows多线程同步--互斥量 windows多线程同 ...

  4. windows多线程同步互斥--总结

    我的windows多线程系列文章: windows多线程--原子操作 windows多线程同步--事件 windows多线程同步--互斥量 windows多线程同步--临界区 windows多线程同步 ...

  5. windows多线程(六) 互斥量Mutex与关键段CriticalSection比较

    一.关键段CS 和 互斥量Mutex 的相同点:都有线程拥有权 关键段和互斥量都有线程拥有权,即可以被一个线程拥有.在 前面讲关键段CS的文章中有说到,关键段结构体的第四个参数保存着拥有该关键段的线程 ...

  6. 转--- 秒杀多线程第七篇 经典线程同步 互斥量Mutex

    阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇一个经典的多线程同步问题> <秒杀多线程第五篇经典线程同步关键段CS> <秒杀多线程第六篇经典线程同步事件Event& ...

  7. [一个经典的多线程同步问题]解决方案三:互斥量Mutex

    本篇通过互斥量来解决线程的同步,学习其中的一些知识. 互斥量也是一个内核对象,它用来确保一个线程独占一个资源的访问.互斥量与关键段的行为非常相似,并且互斥量可以用于不同进程中的线程互斥访问资源.使用互 ...

  8. 多线程面试题系列(7):经典线程同步 互斥量Mutex

    前面介绍了关键段CS.事件Event在经典线程同步问题中的使用.本篇介绍用互斥量Mutex来解决这个问题. 互斥量也是一个内核对象,它用来确保一个线程独占一个资源的访问.互斥量与关键段的行为非常相似, ...

  9. 秒杀多线程第七篇 经典线程同步 互斥量Mutex

    本文转载于:http://blog.csdn.net/morewindows/article/details/7470936 前面介绍了关键段CS.事件Event在经典线程同步问题中的使用.本篇介绍用 ...

随机推荐

  1. 4011: [HNOI2015]落忆枫音

    4011: [HNOI2015]落忆枫音 链接 分析: 原来是一个DAG,考虑如何构造树形图,显然可以给每个点找一个父节点,所以树形图的个数就是$\prod\limits_u deg[u]$. 那么加 ...

  2. Java Swing:JPanel添加边框

    一.JPanel添加不同边框的效果图如下所示 二. 不同边框样式的代码实现 JPanel jpanel = new JPanel(); jpanel.setBorder(BorderFactory.你 ...

  3. Java 原生日志 java.util.logging

    简介 Java 中的 Logging API 让 Java 应用可以记录不同级别的信息,它在debug过程中非常有用,如果系统因为各种各样的原因而崩溃,崩溃原因可以在日志中清晰地追溯,下面让我们来看看 ...

  4. 微信小程序充值及充值回调后的处理

    微信小程序的充值流程与 H5 或 公众号大致差不多,这里简单说一下前端在充值时候的一些操作流程. 用户在小程序中发起充值请求时,一般会先请求自己的服务器,将充值的参数发送给后端,然后后端会去请求微信充 ...

  5. Linux(centos7)之更换安装python3(二)

    Linux不比window好安装python,折腾了好久,终于成功安装上了python,window上一个安装包完事,可惜Linux上python版本太低不好使,还要更换为3版本,百度了好久,教程上总 ...

  6. Unity 自定义编辑器窗口 画线

    最近在学习状态机, 想自己实现一个可视化编辑器, 需要将多个状态之间用线条连接起来, 效果如下: 代码如下: Material m;Vector2 start;Vector2 end;Color co ...

  7. 你这一辈子要用到的C数学函数都在这

       两数相加  #include <stdio.h> int main(void){ int a = 10;  //定义变量a, 把10 赋值给a int b = 20;  //定义变量 ...

  8. SQLMAP学习笔记1 access注入

    SQLMAP学习笔记1  access注入 Sqlmap是开源的自动化SQL注入工具,由Python写成,具有如下特点: 完全支持MySQL.Oracle.PostgreSQL.Microsoft S ...

  9. jenkins的时间与服务器的时间不一致

    解决办法:

  10. VMware vCenter Converter迁移Linux系统虚拟机

    (一)简介VMware vCenter Converter Standalone,是一种用于将虚拟机和物理机转换为 VMware 虚拟机的可扩展解决方案.此外,还可以在 vCenter Server ...