windows多线程(六) 互斥量Mutex与关键段CriticalSection比较
一、关键段CS 和 互斥量Mutex 的相同点:都有线程拥有权
关键段和互斥量都有线程拥有权,即可以被一个线程拥有。在 前面讲关键段CS的文章中有说到,关键段结构体的第四个参数保存着拥有该关键段的线程的句柄,具体如下:
typedef struct _RTL_CRITICAL_SECTION {
PRTL_CRITICAL_SECTION_DEBUG DebugInfo;
//
// The following three fields control entering and exiting the critical
// section for the resource
//
LONG LockCount;
LONG RecursionCount;
HANDLE OwningThread; // from the thread's ClientId->UniqueThread
HANDLE LockSemaphore;
ULONG_PTR SpinCount; // force size on 64-bit systems when packed
} RTL_CRITICAL_SECTION, *PRTL_CRITICAL_SECTION;
第一个参数:PRTL_CRITICAL_SECTION_DEBUG DebugInfo; 调试的时候用的,先不做介绍。
第二个参数:LONG LockCount; 初始化为-1,n表示有n个线程在等待。
第三个参数:LONG RecursionCount; 表示该关键段的拥有线程对此资源获得关键段次数,初为0。
第四个参数:HANDLE OwningThread; 即拥有该关键段的线程句柄
第五个参数:HANDLE LockSemaphore; 实际上是一个自复位事件。
第六个参数:ULONG_PTR SpinCount; 旋转锁的设置,用于多处理器。
现在我们来分析以下程序:
#include<iostream>
#include <windows.h>
using namespace std;
const unsigned int THREAD_NUM = 10;
unsigned int g_Count = 0;
CRITICAL_SECTION cs;
DWORD WINAPI ThreadFunc(LPVOID);
int main()
{
InitializeCriticalSection(&cs);
HANDLE hThread[THREAD_NUM];
for (int i = 0; i < THREAD_NUM; i++)
{
EnterCriticalSection(&cs); // 进入关键段,执行这一句时主线程就获得了这个关键段的拥有权。
hThread[i] = CreateThread(NULL, 0, ThreadFunc,0, 0, NULL);
}
WaitForMultipleObjects(THREAD_NUM, hThread,true,INFINITE);
cout << THREAD_NUM << " 个线程全部返回" << endl;
return 0;
}
DWORD WINAPI ThreadFunc(LPVOID p)
{
LeaveCriticalSection(&cs); // 离开关键段
Sleep(50);
EnterCriticalSection(&cs); // 进入关键段
cout<<"g_Count 的值为:"<<g_Count++<<endl;
LeaveCriticalSection(&cs); // 离开关键段
Sleep(50);
return 0;
}
如下图所示加上两个断点进行调试,正常来说程序应该是依次经过两个断点,但是调试时我们发现,程序会多次重复进入第一个断点,这是因为执行到第一个断点式时主线程就获得了这个关键段的拥有权。

同样地,Mutex也拥有线程所有权,需要了解互斥量看这里。和上面一样,我们写这样一个程序
#include <iostream>
#include <windows.h>
using namespace std;
const unsigned int THREAD_NUM = 10;
unsigned int g_Count = 0;
CRITICAL_SECTION cs;
HANDLE g_Mutex;
DWORD WINAPI ThreadFunc(LPVOID);
int main()
{
InitializeCriticalSection(&cs);
g_Mutex = CreateMutex(NULL, false, NULL); //初始化互斥量为触发状态
HANDLE hTread[THREAD_NUM];
for (int i = 0; i < THREAD_NUM;i++)
{
WaitForSingleObject(g_Mutex, INFINITE); //等待互斥量触发
hTread[i] = CreateThread(NULL, 0, ThreadFunc, 0, 0, NULL);
}
WaitForMultipleObjects(THREAD_NUM, hTread, true, INFINITE);
cout << THREAD_NUM << " 个线程全部返回" << endl;
return 0;
}
DWORD WINAPI ThreadFunc(LPVOID p)
{
//ReleaseMutex(g_Mutex);
Sleep(50);
EnterCriticalSection(&cs); // 进入关键段
cout << "g_Count 的值为:" << g_Count++ << endl;
LeaveCriticalSection(&cs); // 离开关键段
Sleep(50);
ReleaseMutex(g_Mutex); //触发互斥量
return 0;
}
同样地,我们在程序中下两个断点,同样地程序会不经过第二个断点,而重复经过第一个断点。

前面关键段和互斥量两篇文章我们说了关键段CS和互斥量Mutex不能做到线程同步,只能做到临界资源互斥访问,就是因为,他它们都有线程拥有权的原因。
二、关键段CS 和 互斥量Mutex 的不同点:由于互斥量常用于多进程之间的线程互斥,所以它比关键段还多一个很有用的特性——“遗弃”情况的处理。
看下面的程序:
程序一:
#include <stdio.h>
#include <windows.h>
const char MutexName[] = "MyMutex"; //互斥量名字
int main()
{
HANDLE hMutex = CreateMutex(NULL, TRUE, MutexName); //创建互斥量并初始化为未触发状态
printf("互斥量已经创建,按任意键触发\n");
getch();
exit(0); //在互斥量触发前退出程序。
//ReleaseMutex(hMutex); // 触发互斥量
printf("互斥量已经被触发\n");
CloseHandle(hMutex);
return 0;
}
程序二:
#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");
DWORD mRes = WaitForSingleObject(hMutex, INFINITE); // 等待互斥量被触发
if (WAIT_ABANDONED == mRes) //判断互斥量是否被遗弃
{
printf("互斥量被遗弃。\n");
}
//printf("互斥量已经被触发\n");
}
else
{
printf("互斥量打开失败。\n");
}
CloseHandle(hMutex);
return 0;
}
先运行,程序一,然后运行程序二,如下图所示。

此时在,程序一中按任意键,使程序一在互斥量未触发之前退出,程序二输出如下:

这篇是边学边写出来的可能有不正确的地方,欢迎指出!!!!!
windows多线程(六) 互斥量Mutex与关键段CriticalSection比较的更多相关文章
- windows多线程同步--互斥量
关于互斥量的基本概念:百度百科互斥量 推荐参考博客:秒杀多线程第七篇 经典线程同步 互斥量Mutex 注意:互斥量也是一个内核对象,它用来确保一个线程独占一个资源的访问.互斥量与关键段的行为非常相似, ...
- 多线程相关------互斥量Mutex
互斥量(Mutex) 互斥量是一个可以处于两态之一的变量:解锁和加锁.只有拥有互斥对象的线程才具有访问资源的权限.并且互斥量可以用于不同进程中的线程的互斥访问. 相关函数: CreateMutex用于 ...
- 总结windows多线程同步互斥
windows多线程同步互斥--总结 我的windows多线程系列文章: windows多线程--原子操作 windows多线程同步--事件 windows多线程同步--互斥量 windows多线程同 ...
- windows多线程同步互斥--总结
我的windows多线程系列文章: windows多线程--原子操作 windows多线程同步--事件 windows多线程同步--互斥量 windows多线程同步--临界区 windows多线程同步 ...
- windows多线程(五) 互斥量 Mutex
一.互斥量 互斥量是windows的一个内核对象,互斥量与关键段的作用相似,可以用来确保全局资源的互斥访问.并且互斥量可以用在不同的进程中的线程互斥访问全局资源. 二.相关函数说明 使用互斥量Mute ...
- 转--- 秒杀多线程第七篇 经典线程同步 互斥量Mutex
阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇一个经典的多线程同步问题> <秒杀多线程第五篇经典线程同步关键段CS> <秒杀多线程第六篇经典线程同步事件Event& ...
- [一个经典的多线程同步问题]解决方案三:互斥量Mutex
本篇通过互斥量来解决线程的同步,学习其中的一些知识. 互斥量也是一个内核对象,它用来确保一个线程独占一个资源的访问.互斥量与关键段的行为非常相似,并且互斥量可以用于不同进程中的线程互斥访问资源.使用互 ...
- 多线程面试题系列(7):经典线程同步 互斥量Mutex
前面介绍了关键段CS.事件Event在经典线程同步问题中的使用.本篇介绍用互斥量Mutex来解决这个问题. 互斥量也是一个内核对象,它用来确保一个线程独占一个资源的访问.互斥量与关键段的行为非常相似, ...
- 秒杀多线程第七篇 经典线程同步 互斥量Mutex
本文转载于:http://blog.csdn.net/morewindows/article/details/7470936 前面介绍了关键段CS.事件Event在经典线程同步问题中的使用.本篇介绍用 ...
随机推荐
- 3、modleForm组件
1.原生form表单 步骤: 1.models.py ... makemigrations migrate 3.createsuperuser yuan yuan1234 1.addbook:(get ...
- 2_C语言中的数据类型 (六)浮点数
1.1 浮点float,double,long double类型 1.1.1 浮点常量,变量 Float在32位系统下是4个字节,double在32位系统下是8个字节 小 ...
- idea ssm项目出现日志中文乱码,封装的json中的msg字段中文乱码(但是json封装的bean中的字段不乱码)等其他各种项目下的中文乱码解决方案
开头划重点!(敲黑板):rebuild和mvn package的循环往复好几次的操作是解决这个问题的最主要的方法! 经过多次试验,发现这样做就可以正常显示中文了 我说为什么有时候乱码,有时候中文正常, ...
- 【操作系统】C语言编写的FAT16文件系统
[操作系统]C语言编写的FAT16文件系统 这是操作系统的期末课程设计作业之一,主要功能是在物理内存中虚拟出一个1M大小的FAT16的文件系统,然后把它读入内存中,进行具体的文件操作,具体的实用性不大 ...
- Linux 和 Windows 之间共享文件之 samba
导语 如果对windows有过实际操作技巧的人都会明白,在windows下的文件共享加上网络驱动器映射是多么方便的体验,甚至比ftp更加的简单,就像本地多了一块可与他人交流的硬盘一样. 问题 由于性能 ...
- Java+Netty实现的RESTful框架--netty-rest-server
在工作中用Netty做了几个服务,感觉Netty做出来的程序性能好,资源占用少,但是实现Http服务比较麻烦,于是就参考Spring MVC的注解基于Netty实现了一个轻量级的RESTful框架. ...
- 学习java常见dos命令
在java基础学习阶段时一般会在dos命令行下操作文件,这里列出一些常用命令. 打开DOS控制台的方式 按win+r 再输入 cmd 然后回车. 常用DOS命令 d: 回车 盘符切换 (盘符加冒号) ...
- Mysql优化之索引
前言 这几天抽了个时间将<高性能Mysql>看了一下忽觉索引非常之重要,习之然后总结巩固知识.本文索引使用的是InnoDB存储引擎.因为本文并不是说用索引的好处,所以并不会书写QPS之类的 ...
- 木马分析出现python语言,360的安全人员不禁感叹还有这种操作?
几年前,敲诈者木马还是一个默默无闻的木马种类.然而,由于其极强的破坏力和直接且丰厚的财富回报,敲诈者木马这几年已经一跃成为曝光率最高的木马类型——甚至超越了盗号木马.远控木马.网购木马这传统三强.与此 ...
- Mysql数据库的隔离级别
Mysql数据库的隔离级别有四种 1.read umcommitted 读未提交(当前事务可以读取其他事务没提交的数据,会读取到脏数据) 2.read committed 读已提交(当前事务不能读 ...