一、关键段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比较的更多相关文章

  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

    一.互斥量 互斥量是windows的一个内核对象,互斥量与关键段的作用相似,可以用来确保全局资源的互斥访问.并且互斥量可以用在不同的进程中的线程互斥访问全局资源. 二.相关函数说明 使用互斥量Mute ...

  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. 树莓派修改VNC分辨率

    1.打开终端输入 sudo raspi-config 2. 选择 Advanced Options  再选择 Resolution 3.选择想要的分辨率,确定 4.重启

  2. 【转载】钉钉开发c#帮助类 获取用户信息 DingHelper.cs

    using System;using System.Collections.Generic;using System.Configuration;using System.Linq;using Sys ...

  3. Genymotion模拟器安装问题及解决(启动失败,模拟器不能联网)

    安装Genymotion模拟器安装后启动不了,报错: 百度的解决方法是打开VMVBirtualox选中自己的设备点击设置—常规—将版本设置为图中箭头所指的: 但是我这样做的时候发现我的下拉列表中没有6 ...

  4. jenkins使用时出现的问题!

      从安装到日常使用中遇到过的问题和解决方法:   背景/问题:安装时是跳过安装插件过程的,安装好后,我发现里面啥也做不了,连个git的插件都无法下载. 方法:在jenkins的主界面,打开系统管理= ...

  5. Mysql启动失败解决方案 - 个人经验可能不适合所有场景

    以前一直用的Mysql5.5,安装程序是一个exe程序,安装完了相应的服务也给我注册好了,然后直接启动连接即可. 最近升级到了8.0.15,发现和以前不一样了. 8.0.15下载地址 安装解压之后目录 ...

  6. java多线程之述解

    说起线程 就不得不提进程 他们之间的关系很紧密 进程:内存中运行的应用程序 每个进程都有自己的一块内存空间 而线程是进程中的一个执行单元 一个进程中可以有多个线程 多线程的好处就是可以并发操作程序 将 ...

  7. python的字符串格式化

    1.python到底有那几种字符串格式化模块? python有3种格式化字符串的方法: 传统的%字符串格式符 str.format函数 字符串模版template 新的python 3.6+还提供了新 ...

  8. eclipse创建spring boot项目加载不到application.properties配置文件

    在配置文件application.properties中修改了端口号,但重启服务后发现端口号并没有跟着改变,发现是项目启动时没有加载application.properties文件导致 解决:项目-& ...

  9. Inception——Going deeper with convolutions

    1. 摘要 作者提出了一个代号为 Inception 的卷积神经网络架构,这也是作者在 2014 年 ImageNet 大规模视觉识别挑战赛中用于分类和检测的新技术. 通过精心的设计,该架构提高了网络 ...

  10. Tree - AdaBoost with sklearn source code

    In the previous post we addressed some issue of decision tree, including instability, lack of smooth ...