CPP-基础:互斥量
互斥量的用途和临界区很像。它与临界区的差别在于可以跨线程使用,可以用来同步进行多个线程间的数据访问,但是是以牺牲速度为代价的。只有临界区是非核心对象,那么互斥量就是一个核心对象了。核心对象的特点是有所谓的引用计数。锁住一个未被拥有的互斥量,比锁住一个未被拥有的临界区需要花费几乎100倍的时间(数据引用自《Visual C++ 6.0编程学习捷径》)。
VC windows api 多线程---互斥量
与其他几种内核对象不同,互斥对象在操作系统中拥有特殊代码,并由操作系统来管理,操作系统甚至还允许其进行一些其他内核对象所不能进行的非常规操作。为便于理解,可参照图6给出的互斥内核对象的工作模型:
图6 使用互斥内核对象对共享资源的保护:
图(a)中的箭头为要访问资源(矩形框)的线程,但只有第二个线程拥有互斥对象(黑点)并得以进入到共享资源,而其他线程则会被排斥在外(如图(b)所示)。当此线程处理完共享资源并准备离开此区域时将把其所拥有的互斥对象交出(如图(c)所示),其他任何一个试图访问此资源的线程都有机会得到此互斥对象。
Win32 API有一套互斥量的支持函数:
创建互斥量:
HANDLE CreateMutex(LPSECURITY_ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner, LPCTSTR lpName);
* @param lpMutexAttributes 指定安全属性,NULL表示使用默认的属性.
* @param bInitialOwner 指出创建互斥量的线程是否要成为该互斥量的最初拥有.
* TRUE表示拥有,因此互斥量将处于无开放信号状态.
* FALSE表示互斥量不被任何现成拥有,因此处于有开放信号状态.
* @param lpName为NULL或标识该互斥量的一个字符串的地址,任何进程或线程都可以根据此名称使用该互斥量.
* 当应用程序调用CreateMutex()函数时,系统分配一个互斥量的核心对象,把它的名字设为lpName所致的字符串.
* 该名字在进程间共享互斥量。CreateMutex()返回一个标识新互斥量对象的进程相关的句柄.
打开互斥量
HANDLE OpenMutex(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCTSTR lpName);
* @param dwDesiredAccess 可设置为MUTEX_ALL_ACCESS或SYNCHRONIZE.
* @param bInheritHandle 指出该进程创建的子进程能否继承该互斥量.
* @param lpName 指定互斥量的名字.
释放互斥量.
BOOL ReleaseMutex(HANDLE hMutex);
* @param hMutex 要释放的互斥量的句柄.
其唯一的参数hMutex为待释放的互斥对象句柄。至于WaitForSingleObject()和WaitForMultipleObjects()等待函数在互斥对象保持线程同步中所起的作用与在其他内核对象中的作用是基本一致的,也是等待互斥内核对象的通知。但是这里需要特别指出的是:在互斥对象通知引起调用等待函数返回时,等待函数的返回值不再是通常的WAIT_OBJECT_0(对于WaitForSingleObject()函数)或是在WAIT_OBJECT_0到WAIT_OBJECT_0+nCount-1之间的一个值(对于WaitForMultipleObjects()函数),而是将返回一个WAIT_ABANDONED_0(对于WaitForSingleObject()函数)或是在WAIT_ABANDONED_0到WAIT_ABANDONED_0+nCount-1之间的一个值(对于WaitForMultipleObjects()函数)。以此来表明线程正在等待的互斥对象由另外一个线程所拥有,而此线程却在使用完共享资源前就已经终止。除此之外,使用互斥对象的方法在等待线程的可调度性上同使用其他几种内核对象的方法也有所不同,其他内核对象在没有得到通知时,受调用等待函数的作用,线程将会挂起,同时失去可调度性,而使用互斥的方法却可以在等待的同时仍具有可调度性,这也正是互斥对象所能完成的非常规操作之一。
-------------------------------------------
例1:
1 #include <stdio.h>
2 #include <windows.h>
3 #include <string.h>
4 #include <stdlib.h>
5 #define threadnum 10
6 typedef struct THREADDATA
7 {
8 int id;
9 char name[10];
10 int sleep;
11 }THREADDATA;
12
13 HANDLE handleMutex;
14 char * str;
15 DWORD WINAPI ThreadProc( LPVOID lpParam )
16 {
17 THREADDATA *data=(THREADDATA *)lpParam;
18 //WaitForSingleObject(handleMutex,INFINITE);
19 for(int i=0;i<10;i++)
20 {
21 WaitForSingleObject(handleMutex,INFINITE);
22 printf("thread%d:%d\n",data->id,i);
23 ReleaseMutex(handleMutex);
24 Sleep(data->sleep);
25 }
26 // ReleaseMutex(handleMutex);
27 return 0;
28 }
29 int main(int argc, char* argv[])
30 {
31 str=(char*)malloc(30);
32 THREADDATA pData[threadnum];
33 DWORD dwThreadId[threadnum];
34 HANDLE hThread[threadnum];
35 handleMutex= CreateMutex(NULL,false,NULL);
36 for(int i=0;i<threadnum;i++)
37 {
38 pData[i].id=i;
39 sprintf(pData[i].name,"yuguoqing");
40 pData[i].sleep=i*10;
41 hThread[i] = CreateThread(NULL,0,ThreadProc, pData+i, 0, dwThreadId+i);
42 }
43 WaitForMultipleObjects(threadnum, hThread, TRUE, INFINITE);
44 return 0;
45 }
例2:
在编写程序时,互斥对象多用在对那些为多个线程所访问的内存块的保护上,可以确保任何线程在处理此内存块时都对其拥有可靠的独占访问权。下面给出的示例代码即通过互斥内核对象hMutex对共享内存快g_cArray[]进行线程的独占访问保护。下面给出实现代码清单:
// 互斥对象
HANDLE hMutex = NULL;
char g_cArray[];
UINT ThreadProc18(LPVOID pParam)
{
// 等待互斥对象通知
WaitForSingleObject(hMutex, INFINITE);
// 对共享资源进行写入操作
for (int i = ; i < ; i++)
{
g_cArray[i] = 'a';
Sleep();
}
// 释放互斥对象
ReleaseMutex(hMutex);
return ;
}
UINT ThreadProc19(LPVOID pParam)
{
// 等待互斥对象通知
WaitForSingleObject(hMutex, INFINITE);
// 对共享资源进行写入操作
for (int i = ; i < ; i++)
{
g_cArray[ - i - ] = 'b';
Sleep();
}
// 释放互斥对象
ReleaseMutex(hMutex);
return ;
}
……
void CSample08View::OnMutex()
{
// 创建互斥对象
hMutex = CreateMutex(NULL, FALSE, NULL);
// 启动线程
AfxBeginThread(ThreadProc18, NULL);
AfxBeginThread(ThreadProc19, NULL);
// 等待计算完毕
Sleep();
// 报告计算结果
CString sResult = CString(g_cArray);
AfxMessageBox(sResult);
}
MFC中通过CMutex类
互斥对象在MFC中通过CMutex类进行表述。使用CMutex类的方法非常简单,在构造CMutex类对象的同时可以指明待查询的互斥对象的名字,在构造函数返回后即可访问此互斥变量。CMutex类也是只含有构造函数这唯一的成员函数,当完成对互斥对象保护资源的访问后,可通过调用从父类CSyncObject继承的UnLock()函数完成对互斥对象的释放。CMutex类构造函数原型为:
CMutex( BOOL bInitiallyOwn = FALSE, LPCTSTR lpszName = NULL, LPSECURITY_ATTRIBUTES lpsaAttribute = NULL );
该类的适用范围和实现原理与API方式创建的互斥内核对象是完全类似的,但要简洁的多,下面给出就是对前面的示例代码经CMutex类改写后的程序实现清单:
// MFC互斥类对象
CMutex g_clsMutex(FALSE, NULL);
UINT ThreadProc27(LPVOID pParam)
{
// 等待互斥对象通知
g_clsMutex.Lock();
// 对共享资源进行写入操作
for (int i = ; i < ; i++)
{
g_cArray[i] = 'a';
Sleep();
}
// 释放互斥对象
g_clsMutex.Unlock();
return ;
}
UINT ThreadProc28(LPVOID pParam)
{
// 等待互斥对象通知
g_clsMutex.Lock();
// 对共享资源进行写入操作
for (int i = ; i < ; i++)
{
g_cArray[ - i - ] = 'b';
Sleep();
}
// 释放互斥对象
g_clsMutex.Unlock();
return ;
}
……
void CSample08View::OnMutexMfc()
{
// 启动线程
AfxBeginThread(ThreadProc27, NULL);
AfxBeginThread(ThreadProc28, NULL);
// 等待计算完毕
Sleep();
// 报告计算结果
CString sResult = CString(g_cArray);
AfxMessageBox(sResult);
}
CPP-基础:互斥量的更多相关文章
- [linux basic 基础]----同步互斥量
互斥量,运行程序元锁住某个对象,使得每次只能有一个线程访问它:为了控制对关键代码的访问,必须在进入这段代码之前锁住一个互斥量,然后在完成操作之后解锁它 :基本函数与用于信号量的函数非常相似#inclu ...
- 1.linux系统基础笔记(互斥量、信号量)
操作系统是很多人每天必须打交道的东西,因为在你打开电脑的一刹那,随着bios自检结束,你的windows系统已经开始运行了.如果问大家操作系统是什么?可能有的人会说操作系统就是windows,就是那些 ...
- Linux/Unix 线程同步技术之互斥量(1)
众所周知,互斥量(mutex)是同步线程对共享资源访问的技术,用来防止下面这种情况:线程A试图访问某个共享资源时,线程B正在对其进行修改,从而造成资源状态不一致.与之相关的一个术语临界区(critic ...
- Linux 多线程互斥量互斥
同步 同一个进程中的多个线程共享所在进程的内存资源,当多个线程在同一时刻同时访问同一种共享资源时,需要相互协调,以避免出现数据的不一致和覆盖等问题,线程之间的协调和通信的就叫做线程的同步问题, 线程同 ...
- 共享内存+互斥量实现linux进程间通信 分类: Linux C/C++ 2015-03-26 17:14 67人阅读 评论(0) 收藏
一.共享内存简介 共享内存是进程间通信中高效方便的方式之一.共享内存允许两个或更多进程访问同一块内存,就如同 malloc() 函数向不同进程返回了指向同一个物理内存区域的指针,两个进程可以对一块共享 ...
- Linux:使用互斥量进行线程同步
基础知识 同步概念 所谓同步,即同时起步,协调一致.不同的对象,对"同步"的理解方式略有不同.如,设备同步,是指在两个设备之间规定一个共同的时间参考:数据库同步,是指让两个或多个数 ...
- linux 线程的同步 一 (互斥量和信号量)
互斥量(Mutex) 互斥量表现互斥现象的数据结构,也被当作二元信号灯.一个互斥基本上是一个多任务敏感的二元信号,它能用作同步多任务的行为,它常用作保护从中断来的临界段代码并且在共享同步使用的资源. ...
- C++多线程同步之Mutex(互斥量)
原文链接: http://blog.csdn.net/olansefengye1/article/details/53086141 一.互斥量Mutex同步多线程 1.Win32平台 相关函数和头文件 ...
- 以Linux下的测试程序说明递归型互斥量和普通互斥量的区别
先贴代码和测试结果 // Mutex.h: 对pthread的互斥量的RAII包装 #ifndef _MUTEX_H_ #define _MUTEX_H_ #include <stdio.h&g ...
- 信号量和互斥量C语言示例理解线程同步
Table of Contents 1. 线程同步 1.1. 用信号量进行同步 1.2. 用互斥量进行同步 2. 参考资料 线程同步 了解线程信号量的基础知识,对深入理解python的线程会大有帮助. ...
随机推荐
- JS实现中英文混合文字溢出友好截取功能
在显示字符串的时候,避免字符串过长往往会对字符串进行截取操作,通常会用到js的 substr 或者 substring方法, 以及 字符串的length属性 substr() 方法可在字符串中抽取从 ...
- 一:Nginx知识整理
Nginx与服务器集群 一:集群 1.什么是集群 集 合在一起 放在一起 群 一堆 很多 服务器架构集群:多台服务器组成的响应大并发,高数据量访问的架构体系. 分布式服务器架构: 特点: 1)成本高 ...
- ActiveMQ整合spring结合项目开发流程(生产者和消费者)总结
一:生产者代码编写: 1.配置pom.xml引入相关坐标 <dependencies> <!-- spring开发测试 --> <dependency> <g ...
- Window 10 安装 MySQL
1.下载 点击官网下载路径下载压缩包 点击第一个按钮后出现如下界面 下载后解压缩,我这里是放在C:\web\目录下 2.创建配置文件 注意:my.ini文件是自己创建的配置文件 文件内容如下: [my ...
- springboot项目作为war包运行
一.首先是pom文件中设置打成war包 < packaging>war< /packaging> 二.然后是修改依赖: <dependency> <group ...
- Spring事务不起作用原因
首先声明: Checked异常继承java.lang.Exception类.Unchecked异常继承自java.lang.RuntimeException类. 而,Spring的事务实现采用基于AO ...
- Windows安装配置xampp
建议大家直接看原文 1.安装XAMPP 进入https://www.apachefriends.org/zh_cn/index.html页面下载XAMPP 2 3.打开xampp控制版 4.修改apa ...
- maven(04)--一个简单的项目
简单介绍 一个maven项目,使用hibernate框架,实现向mysql数据库中添加和获取操作,其他操作也是类似 如果你没有hibernate,那么也不要紧,这里主要介绍如何在一个maven项目中引 ...
- 移动端布局注意事项与less
用Koala实现less的实时编译 1.下载Koala(Koala可以实现实时编译) 2.把CSS文件夹(如index.css,index.less)拖到Koala中 3.点击到需要编译的index. ...
- window.onload和3的小游戏
window.onload出现的原因? 我们都知道页面的代码顺序是从上往下进行加载,很多时候我们要对页面中的某一个模块进行操作,这时候我们常常使用javascript代码来进行操作.为了能够保证操作 ...