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在经典线程同步问题中的使用.本篇介绍用 ...
随机推荐
- python基础学习2-easygui框架编程
#!/usr/bin/env python # -*- coding:utf-8 -*- import easygui as g #导入方式一 #导入方式2 #from easygui import ...
- 非局部均值滤波算法的python实现
如题,比opencv自带的实现效果好 #coding:utf8 import cv2 import numpy as np def psnr(A, B): return 10*np.log(255*2 ...
- 使用Keil下载单独的Hex文件到单片机内
前言 初学STM32时,是通过串口1把Hex文件下载进STM32的,需要一个串口模块,而且还要设置BOOT0和BOOT1电平,然后通过FlyMcu软件进行下载,这也是一种不错的方法,这里我要介绍的是使 ...
- PageIOLatch和PageLatch
Latch是轻量级的锁,它是SQL Server内部用来同步资源访问的一个数据结构,使数据的访问同步有序,这意味着,当一个线程获得资源R的Latch的独占使用权时,如果其他的线程也想访问这个Latch ...
- 【oracle】oracle常用命令汇总
查看数据库状态(普通用户登录要保证数据库是open状态) SQL> select status from v$instance; 创建用户(新用户需要授予连接权限才能连上数据库) SQL> ...
- javascript中encodeURI和decodeURI方法使用介绍
encodeURI和decodeURI是成对来使用的,因为浏览器的地址栏有中文字符的话,可以会出现不可预期的错误, 所以可以encodeURI把非英文字符转化为英文编码,decodeURI可以用来把字 ...
- 开发人员常用的DOS命令
1.远程连接:mstsc /admin 2.开启服务:services.msc 3.打开注册表:regedit 4.IIS服务器重启:iisreset 5.打开记事本:notepad 6.查看系统信息 ...
- 《Python 网络爬虫权威指南》 分享 pdf下载
链接:https://pan.baidu.com/s/1ZYEinjOwM_5dBIVftN42tg 提取码:1om6
- InsertionSort 直接插入排序(java)
排序思想: 相当于一堆数字,一开始先取出2个数排序,2个数排好序之后,再从一堆数字里面取一个数排序,直到结束伪代码: INSERTION_SORT(A) for j = 2 to A.length k ...
- elementUI实现前端分页
按照他的文档来写分页,最主要的是el-table里面展示的数据怎么处理 <el-table :data="AllCommodityList.slice((currentPage-1)* ...