一、互斥量

互斥量是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. python基础学习1 -异常捕获

    #!/usr/bin/env python # -*- coding:utf-8 -*- #-------try-except try: file_name = input("请输入需要打开 ...

  2. django学习笔记(1)

    Django 特点 强大的数据库功能     用python的类继承,几行代码就可以拥有一个丰富,动态的数据库操作接口(API),如果需要你也能执行SQL语句 自带的强大的后台功能     几行简单的 ...

  3. SQL Server 中SELECT INTO 和 INSERT INTO SELECT 两种表复制语句

    1.INSERT INTO SELECT语句 语句形式为:Insert into Table2(field1,field2,...) select value1,value2,... from Tab ...

  4. kali base64命令的使用

    1.启动终端 2.输入base64 3.输入需要编码的字符串 4,CTRL+D,结束输入,在屏幕上回显输出结果

  5. window下查杀占用端口的进程

    一. 查找占用的端口进程号,比如8080 C:> netstat –ano|findstr 8080 C:\Users\chry>netstat -ano | findstr 8080 T ...

  6. HDU - 5289 Assignment (RMQ+二分)(单调队列)

    题目链接: Assignment  题意: 给出一个数列,问其中存在多少连续子序列,使得子序列的最大值-最小值<k. 题解: RMQ先处理出每个区间的最大值和最小值(复杂度为:n×logn),相 ...

  7. jsp标签在JavaScript中使用时,可能会出现的一个问题。

    直接上代码 <script type="text/javascript"> var E = window.wangEditor; var editor = new E( ...

  8. python破解网吧收费系统,远控网吧电脑设备!

      我今天呢 , 我就没事跟着朋友喝酒喝酒啊.喝了很多啊.晚上到旁边的酒店开了一个房间,到了酒店才十点! 感觉没啥事情干的,那就去网吧走走看把,看到是一个嘟嘟牛的,和上次是一样的.还是照常用MS170 ...

  9. Spring学习(4)IOC容器配置bean:定义与实例化

    一.  IOC容器配置 1. 一些概念 (1)IOC容器: 定义:具有管理对象和管理对象之间的依赖关系的容器. 作用:应用程序无需自己创建对象,对象由IOC容器创建并组装.BeanFactory是IO ...

  10. Spark Streaming流式处理

    Spark Streaming介绍 Spark Streaming概述 Spark Streaming makes it easy to build scalable fault-tolerant s ...