当前位置: 首页 > 编程日记 > 正文

(转)互斥对象锁和临界区锁性能比较 .

在Win32平台上进行多线程编程,常会用到锁。下边用C++实现了互斥对象(Mutex)锁和临界区(CRITICAL_SECTION)锁,以加深理解和今后方便使用。代码已在VS2005环境下编译测试通过。

Lock.h

[cpp] view plaincopyprint?
  1. #ifndef _Lock_H
  2. #define _Lock_H
  3. #include <windows.h>
  4. //锁接口类
  5. class ILock
  6. {
  7. public:
  8. virtual ~ILock() {}
  9. virtual void Lock() const = 0;
  10. virtual void Unlock() const = 0;
  11. };
  12. //互斥对象锁类
  13. class Mutex : public ILock
  14. {
  15. public:
  16. Mutex();
  17. ~Mutex();
  18. virtual void Lock() const;
  19. virtual void Unlock() const;
  20. private:
  21. HANDLE m_mutex;
  22. };
  23. //临界区锁类
  24. class CriSection : public ILock
  25. {
  26. public:
  27. CriSection();
  28. ~CriSection();
  29. virtual void Lock() const;
  30. virtual void Unlock() const;
  31. private:
  32. CRITICAL_SECTION m_critclSection;
  33. };
  34. //锁
  35. class CMyLock
  36. {
  37. public:
  38. CMyLock(const ILock&);
  39. ~CMyLock();
  40. private:
  41. const ILock& m_lock;
  42. };
  43. #endif

#ifndef _Lock_H #define _Lock_H #include <windows.h> //锁接口类 class ILock { public: virtual ~ILock() {} virtual void Lock() const = 0; virtual void Unlock() const = 0; }; //互斥对象锁类 class Mutex : public ILock { public: Mutex(); ~Mutex(); virtual void Lock() const; virtual void Unlock() const; private: HANDLE m_mutex; }; //临界区锁类 class CriSection : public ILock { public: CriSection(); ~CriSection(); virtual void Lock() const; virtual void Unlock() const; private: CRITICAL_SECTION m_critclSection; }; //锁 class CMyLock { public: CMyLock(const ILock&); ~CMyLock(); private: const ILock& m_lock; }; #endif

Lock.cpp

[cpp] view plaincopyprint?
  1. #include "Lock.h"
  2. //---------------------------------------------------------------------------
  3. //创建一个匿名互斥对象
  4. Mutex::Mutex()
  5. {
  6. m_mutex = ::CreateMutex(NULL, FALSE, NULL);
  7. }
  8. //销毁互斥对象,释放资源
  9. Mutex::~Mutex()
  10. {
  11. ::CloseHandle(m_mutex);
  12. }
  13. //确保拥有互斥对象的线程对被保护资源的独自访问
  14. void Mutex::Lock() const
  15. {
  16. DWORD d = WaitForSingleObject(m_mutex, INFINITE);
  17. }
  18. //释放当前线程拥有的互斥对象,以使其它线程可以拥有互斥对象,对被保护资源进行访问
  19. void Mutex::Unlock() const
  20. {
  21. ::ReleaseMutex(m_mutex);
  22. }
  23. //---------------------------------------------------------------------------
  24. //初始化临界资源对象
  25. CriSection::CriSection()
  26. {
  27. ::InitializeCriticalSection(&m_critclSection);
  28. }
  29. //释放临界资源对象
  30. CriSection::~CriSection()
  31. {
  32. ::DeleteCriticalSection(&m_critclSection);
  33. }
  34. //进入临界区,加锁
  35. void CriSection::Lock() const
  36. {
  37. ::EnterCriticalSection((LPCRITICAL_SECTION)&m_critclSection);
  38. }
  39. //离开临界区,解锁
  40. void CriSection::Unlock() const
  41. {
  42. ::LeaveCriticalSection((LPCRITICAL_SECTION)&m_critclSection);
  43. }
  44. //---------------------------------------------------------------------------
  45. //利用C++特性,进行自动加锁
  46. CMyLock::CMyLock(const ILock& m) : m_lock(m)
  47. {
  48. m_lock.Lock();
  49. }
  50. //利用C++特性,进行自动解锁
  51. CMyLock::~CMyLock()
  52. {
  53. m_lock.Unlock();
  54. }

#include "Lock.h" //--------------------------------------------------------------------------- //创建一个匿名互斥对象 Mutex::Mutex() { m_mutex = ::CreateMutex(NULL, FALSE, NULL); } //销毁互斥对象,释放资源 Mutex::~Mutex() { ::CloseHandle(m_mutex); } //确保拥有互斥对象的线程对被保护资源的独自访问 void Mutex::Lock() const { DWORD d = WaitForSingleObject(m_mutex, INFINITE); } //释放当前线程拥有的互斥对象,以使其它线程可以拥有互斥对象,对被保护资源进行访问 void Mutex::Unlock() const { ::ReleaseMutex(m_mutex); } //--------------------------------------------------------------------------- //初始化临界资源对象 CriSection::CriSection() { ::InitializeCriticalSection(&m_critclSection); } //释放临界资源对象 CriSection::~CriSection() { ::DeleteCriticalSection(&m_critclSection); } //进入临界区,加锁 void CriSection::Lock() const { ::EnterCriticalSection((LPCRITICAL_SECTION)&m_critclSection); } //离开临界区,解锁 void CriSection::Unlock() const { ::LeaveCriticalSection((LPCRITICAL_SECTION)&m_critclSection); } //--------------------------------------------------------------------------- //利用C++特性,进行自动加锁 CMyLock::CMyLock(const ILock& m) : m_lock(m) { m_lock.Lock(); } //利用C++特性,进行自动解锁 CMyLock::~CMyLock() { m_lock.Unlock(); }


    下边是测试代码

[cpp] view plaincopyprint?
  1. // MyLock.cpp : 定义控制台应用程序的入口点。
  2. //
  3. #include <iostream>
  4. #include <process.h>
  5. #include <time.h>
  6. #include "Lock.h"
  7. using namespace std;
  8. #define ENABLE_MUTEX
  9. #define ENABLE_CRITICAL_SECTION
  10. #if defined (ENABLE_MUTEX)
  11. //创建一个互斥对象类型锁
  12. Mutex g_Lock;
  13. #elif defined (ENABLE_CRITICAL_SECTION)
  14. //创建一个临界区类型锁
  15. CriSection g_Lock;
  16. #endif
  17. void LockCompare(int &iNum)
  18. {
  19. CMyLock lock1(g_Lock);
  20. iNum++;
  21. }
  22. //线程函数
  23. unsigned int __stdcall StartThread(void *pParam)
  24. {
  25. char *pMsg = (char *)pParam;
  26. if (!pMsg)
  27. {
  28. return (unsigned int)1;
  29. }
  30. CMyLock lock2(g_Lock);
  31. clock_t tStart,tEnd;
  32. tStart = clock();
  33. int iNum = 0;
  34. for (int i = 0; i < 100000; i++)
  35. {
  36. LockCompare(iNum);
  37. }
  38. tEnd = clock();
  39. #if defined (ENABLE_MUTEX)
  40. cout<<"The lock type is mutex, time = "<<(tEnd - tStart)<<" ms."<<endl;
  41. #elif defined (ENABLE_CRITICAL_SECTION)
  42. cout<<"The lock type is critical section, time = "<<(tEnd - tStart)<<" ms."<<endl;
  43. #endif
  44. return (unsigned int)0;
  45. }
  46. int main(int argc, char* argv[])
  47. {
  48. HANDLE hThread1, hThread2;
  49. unsigned int uiThreadId1, uiThreadId2;
  50. char *pMsg1 = "First print thread.";
  51. char *pMsg2 = "Second print thread.";
  52. //创建两个工作线程,分别打印不同的消息
  53. hThread1 = (HANDLE)_beginthreadex(NULL, 0, &StartThread, (void *)pMsg1, 0, &uiThreadId1);
  54. hThread2 = (HANDLE)_beginthreadex(NULL, 0, &StartThread, (void *)pMsg2, 0, &uiThreadId2);
  55. //等待线程结束
  56. DWORD dwRet = WaitForSingleObject(hThread1,INFINITE);
  57. if ( dwRet == WAIT_TIMEOUT )
  58. {
  59. TerminateThread(hThread1,0);
  60. }
  61. dwRet = WaitForSingleObject(hThread2,INFINITE);
  62. if ( dwRet == WAIT_TIMEOUT )
  63. {
  64. TerminateThread(hThread2,0);
  65. }
  66. //关闭线程句柄,释放资源
  67. ::CloseHandle(hThread1);
  68. ::CloseHandle(hThread2);
  69. system("pause");
  70. return 0;
  71. }

// MyLock.cpp : 定义控制台应用程序的入口点。 // #include <iostream> #include <process.h> #include <time.h> #include "Lock.h" using namespace std; #define ENABLE_MUTEX #define ENABLE_CRITICAL_SECTION #if defined (ENABLE_MUTEX) //创建一个互斥对象类型锁 Mutex g_Lock; #elif defined (ENABLE_CRITICAL_SECTION) //创建一个临界区类型锁 CriSection g_Lock; #endif void LockCompare(int &iNum) { CMyLock lock1(g_Lock); iNum++; } //线程函数 unsigned int __stdcall StartThread(void *pParam) { char *pMsg = (char *)pParam; if (!pMsg) { return (unsigned int)1; } CMyLock lock2(g_Lock); clock_t tStart,tEnd; tStart = clock(); int iNum = 0; for (int i = 0; i < 100000; i++) { LockCompare(iNum); } tEnd = clock(); #if defined (ENABLE_MUTEX) cout<<"The lock type is mutex, time = "<<(tEnd - tStart)<<" ms."<<endl; #elif defined (ENABLE_CRITICAL_SECTION) cout<<"The lock type is critical section, time = "<<(tEnd - tStart)<<" ms."<<endl; #endif return (unsigned int)0; } int main(int argc, char* argv[]) { HANDLE hThread1, hThread2; unsigned int uiThreadId1, uiThreadId2; char *pMsg1 = "First print thread."; char *pMsg2 = "Second print thread."; //创建两个工作线程,分别打印不同的消息 hThread1 = (HANDLE)_beginthreadex(NULL, 0, &StartThread, (void *)pMsg1, 0, &uiThreadId1); hThread2 = (HANDLE)_beginthreadex(NULL, 0, &StartThread, (void *)pMsg2, 0, &uiThreadId2); //等待线程结束 DWORD dwRet = WaitForSingleObject(hThread1,INFINITE); if ( dwRet == WAIT_TIMEOUT ) { TerminateThread(hThread1,0); } dwRet = WaitForSingleObject(hThread2,INFINITE); if ( dwRet == WAIT_TIMEOUT ) { TerminateThread(hThread2,0); } //关闭线程句柄,释放资源 ::CloseHandle(hThread1); ::CloseHandle(hThread2); system("pause"); return 0; }


    在线程函数StartThread中,循环100000次,对保护资源“iNum ”反复加锁,解锁。编译,运行5次,将每次打印的线程锁切换耗时时间记录下来。之后,将测试代码中的宏 #define ENABLE_MUTEX 注释掉,禁掉互斥锁,启用临界区锁,重新编译代码,运行5次。下边是分别是互斥锁和临界区锁耗时记录(不同机器上耗时会不同):

 

互斥锁

线程Id

耗时 / ms

总计

1

141

125

125

125

125

641

2

140

125

140

125

156

686

 

临界区锁

线程Id

耗时 / ms

总计

1

15

16

31

31

31

124

2

31

31

31

16

31

140

 

    互斥锁总共耗时:641+686=1327 ms,而临界区锁:124+140=264 ms。显而易见,临界区锁耗时比互斥锁耗时节约了大概5倍的时间。

    总结:1、在同一个进程的多线程同步锁,宜用临界区锁,它比较节约线程上下文切换带来的系统开销。但因临界区工作在用户模式下,所以不能对不同进程中的多线程进行同步。2、因互斥对象锁属于内核对象,所以在进行多线程同步时速度会比较慢,但是可以在不同进程的多个线程之间进行同步。

 转自:http://blog.csdn.net/chexlong/article/details/7060425

转载于:https://www.cnblogs.com/wonderKK/archive/2012/06/14/2549478.html

相关文章:

CentOS6.5 下sciki-learn numpy scipy 的安装

CentOS6.5 下sciki-learn numpy scipy 的安装软件安装CentOSPython之前用的一直是CentOS 7&#xff0c; 后来觉的软件安装太麻烦就改到了Ubuntu&#xff0c; 这些Python 的包在Ubuntu下安装几乎是无脑的&#xff0c;用apt-get 安装 Ipython 的时候会自动下载numpy, scipy 和 ma…

2021年甘肃省副高考试成绩查询,2021年甘肃卫生资格考试成绩查询-中国卫生人才网...

国家卫生资格考试网为您发布 2021年甘肃卫生资格考试成绩查询-中国卫生人才网&#xff0c;同步中国卫生人才网信息&#xff1a;2021甘肃卫生资格成绩查询。更多关于卫生资格成绩,卫生资格考试,2021卫生资格考试,国家卫生资格成绩查询的信息内容&#xff0c;请关注国家卫生资格考…

OWIN初探(转)

什么是 OWIN &#xff1f; OWIN 的全称是 "Open Web Interface for .NET"&#xff0c; OWIN 在 .NET Web 服务器和 .NET Web 应用之间定义了一套标准的接口&#xff0c; 其目的是为了实现服务器与应用之间的解耦&#xff0c; 鼓励为 .NET Web 应用开发简单模块。 OWI…

JavaMail学习笔记(一)、理解邮件传输协议(SMTP、POP3、IMAP、MIME)

电子邮件需要在邮件客户端和邮件服务器之间&#xff0c;以及两个邮件服务器之间进行传递&#xff0c;就必须遵循一定的规则&#xff0c;这些规则就是邮件传输协议。SMTP协议定了邮件客户端与SMTP服务之间&#xff0c;以及两台SMTP服务器之间发送邮件的通信规则&#xff1b;POP3…

怎样设计一个商城项目?

这两天公司要做一个商城项目&#xff0c;网上搜了很多没找到完整的、有结构体系的资料&#xff0c;可能这件事本身并不难&#xff0c;但是对新手非常不友好&#xff0c;所以我借机把这些碎片化的资料尝试整理成一个有体系的资料&#xff0c;希望能对你有帮助。资料来源包括&…

台式计算机刚换的显示屏怎么设置,台式机怎么样切换显示器

我的台式机是双显示器&#xff0c;该怎么样去切换呢?下面由小编给你做出详细的台式机切换显示器方法介绍!希望对你有帮助!台式机切换显示器方法一&#xff1a;需要用到的硬件&#xff1a;1、支持双视频信号输出的显卡。如一块显卡支持VGA输出&#xff0c;又同时支持DVI输出。2…

c# html文本编辑器,C#实现简单文本编辑器

本文实例为大家分享了C#实现简单文本编辑器的具体代码&#xff0c;供大家参考&#xff0c;具体内容如下建立一个窗体文件&#xff0c;实现对文件的编辑保存和对txt文件的打开界面设计&#xff1a;程序源代码&#xff1a;//form1.csusing System;using System.Collections.Gener…

spark1.4加载mysql数据 创建Dataframe及join操作连接方法问题

首先我们使用新的API方法连接mysql加载数据 创建DF import org.apache.spark.sql.DataFrame import org.apache.spark.{SparkContext, SparkConf} import org.apache.spark.sql.{SaveMode, DataFrame} import scala.collection.mutable.ArrayBuffer import org.apache.spark…

新机器学习库TensorFlow Privacy问世:旨在保护敏感数据

在最近的一篇博文中&#xff0c;TensorFlow宣布推出TensorFlow Privacy。这是一个开源库&#xff0c;它允许研究人员和开发人员构建具有强大隐私保护功能的机器学习模型。基于强大的数学确定性&#xff08;mathematical guarantees&#xff09;&#xff0c;使用本库可以确保用户…

HDU 1596 find the safest road (Floyd)

题目链接 本来对弗洛伊德很没信心&#xff0c;1000个城市&#xff0c;还好&#xff0c;还是过了&#xff0c;最裸的有4000ms&#xff0c;因为是无向图加了下优化&#xff0c;3000ms&#xff0c;这个。。。。 #include <stdio.h> #include <string.h> double p[1001…

PHP学习 文件操作函数的应用--简单网络留言模板

1 <?php2 /**3 网络留言板模式4 主要运用到的函数有5 fopen fclose flock fwrite fread explode list6 */7 ?>8 <meta http-equiv"Content-Type" content"text/html;charsetutf-8">9 <?php error_reporting(E_ALL &…

刷过一题之黑魔法师之门

经过了16 个工作日的紧张忙碌&#xff0c;未来的人类终于收集到了足够的能源。然而在与Violet星球的战争中&#xff0c;由于Z 副官的愚蠢&#xff0c;地球的领袖applepi 被邪恶的黑魔法师Vani 囚禁在了Violet 星球。为了重启Nescaf这一宏伟的科技工程&#xff0c;人类派出了一支…

浅谈Javascript事件模拟

事件是用来描述网页中某一特定有趣时刻的&#xff0c;众所周知事件通常是在由用户和浏览器进行 交互时触发&#xff0c;其实不然&#xff0c;通过Javascript可以在任何时间触发特定的事件&#xff0c;并且这些事件与浏览器创建的事件是相同的。这就意味着会有适当的事件冒 泡&a…

程序员成熟的几个标志

转载自&#xff1a;http://blog.csdn.net/linux_loajie/article/details/7698551 程序员成熟的标志 程序员在经历了若干年编程工作之后&#xff0c;很想知道自己水平到底如何&#xff1f;自己是否已经成为成熟的程序员&#xff1f;虽然程序员会对自己有一个自我评价&#xff0c…

云平台屡次停摆,核心系统事故频发?您的运维系统该升级了!

3月3日凌晨&#xff0c;阿里云出现宕机故障&#xff0c;受宕机故障影响&#xff0c;华北不少互联网公司 APP、网站纷纷瘫痪&#xff0c;一大波程序员、运营和运维不得不从被窝里爬起来干活。网友“上海蓝盟网络夏立成”调侃&#xff0c;“阿里云一年一宕机&#xff0c;今年特别…

yii1框架,事务使用方法

Yii1框架事务操作方法如下&#xff1a; $transaction Yii::app()->db->beginTransaction();//创建事务 $transaction->commit();//提交事务 $transaction->rollback();//回滚事务下面使用try&#xff0c;throw&#xff0c;catch配合使用事务&#xff1a; 1 // 以下…

竖直菜单 html,jQuery实现的网页竖向菜单效果代码

本文实例讲述了jQuery实现的网页竖向菜单效果代码。分享给大家供大家参考。具体如下&#xff1a;这是一款基于jQuery实现竖向的网页菜单代码&#xff0c;可折叠展开的二级网页菜单&#xff0c;修改一下可用在后台管理中&#xff0c;显示在左侧的那种管理菜单。jquery加入后方便…

可以检验计算机配置的游戏软件,检测游戏配置的软件-有没有自己检验电脑配置是否符合游戏要求配置 – 手机爱问...

2018-03-28电脑配置是否够好如果楼主你这个配制已经配了的话就没什么好说的了 如果你没配 今天是别人给你写的话 那就千万别配 因为根本是一套垃圾东西 给你介绍一套 CPU&#xff1a;5200 够了 主板&#xff1a;七彩红 770 370 比华硕M2N68 400 NF芯片的划算 还可以组成3A平台 …

Linux实战教学笔记32:企业级Memcached服务应用实践

一&#xff0c; Memcached介绍 1.1 Memcached与常见同类软件对比 &#xff08;1&#xff09;Memcached是什么&#xff1f; Memcached是一个开源的&#xff0c;支持高性能&#xff0c;高并发的分布式内存缓存系统&#xff0c;由C语言编写&#xff0c;总共2000多行代码。从软件名…

嵌入式开发入门(2)

开发平台和硬件设备。我给的只是一种入门知识&#xff0c;具体如何应用请自助思考。所以请不要想着和我搭建同样的硬件平台。你要学习的是入门知识&#xff0c;换个芯片你一样可以这样做。 Ps&#xff1a;如果你想搭建试验平台直接买STM32F103的开发板&#xff0c;淘宝一把一把…

计算机四级网络工程题库,2016计算机四级网络工程师题库

2016计算机四级网络工程师题库一、选择题1、 以下关于OSPF协议技术特征的描述中&#xff0c;哪个是错误的?A.OSPF协议使用层次结构的区域划分B.它将一个自治系统内部划分成若干区域与主干区域(backbone area.C.主干区域连接多个区域&#xff0c;主干区域内部的路由器叫做主干路…

英语计算机作文初中.,初中英语作文:电脑游戏

Computer Games电脑游戏Computer games is a hot topic nowadays. Some people hold that it is bad. And others hold that it is good. In my view, whether good or bad is determined by the players.现在&#xff0c;电脑游戏是一个非常火的话题。一些人认为电脑游戏是不好…

计算机英语缩写AGP,IT行业常用计算机缩略语

IT行业常用计算机缩略语导语&#xff1a;信息技术缩写为IT&#xff0c;是主要用于管理和处理信息所采用的各种技术的总称。下面是YJBYS小编收集整理的IT行业常用计算机缩略语&#xff0c;希望对你有帮助!ADC     Analog-to-Digital Conventer      模数转换器ADO  …

山东计算机类好的民办大学,山东四大坑人学校-山东坑人的民办大学(野鸡大学)...

选择科目测一测我能上哪些大学选择科目领取你的专属报告>选择省份关闭请选择科目确定v>山东省作为高考大省&#xff0c;每年考生的竞争力很大&#xff0c;因此在选择院校的时候更需要考虑清楚。坊间传闻&#xff0c;“山东十大垃圾大学”是非常坑人的&#xff0c;那么山东…

java中数组的一些笔记

数组&#xff08;相同数据类型的集合&#xff09;&#xff1a;是引用数据类型&#xff0c;数组的中的每个元素相当于数组的成员变量int [] num/ int num[]int nums [] new int [5];//创建了数组的对象并且指定了数组的长度。数组的长度一旦指定就不能更改index 下标 索引 从零…

计算机组成 试题,计算机组成典型试题及答案

计算机组成典型试题及答案计算机组成的任务是在指令集系统结构确定分配给硬件系统的功能和概念结构之后,研究各组成部分的内部构造和相互联系&#xff0c;那么计算机组成原理考试考什么呢?下面yjbys小编为大家分析计算机组成原理典型试题及答案如下&#xff1a;1.在计算机内部…

15-11-23:system指令

CMD命令&#xff1a;开始&#xff0d;>运行&#xff0d;>键入cmd或command&#xff08;在命令行里可以看到系统版本、文件系统版本&#xff09; 1. appwiz.cpl&#xff1a;程序和功能 2. calc&#xff1a;启动计算器 3. certmgr.msc&#xff1a;证书管理实用程序 4. c…

J2EE的13种核心技术规范

J2EE主要用于创建可扩展的企业应用&#xff0c;包括13种核心技术规范&#xff1a; 1. JDBC&#xff08;Java Database Connectivity&#xff0c;Java数据库连接&#xff09; JDBC以一种统一的方式对各种各样的数据库进行存取&#xff0c;JDBC定义了4中不同的驱动程序&#xff1…

计算机教师简介50字,教师风采个人简介50字数.docx

教师个人简介 50 字大全例一&#xff1a;大家好&#xff0c;我叫王力央。今年 12 岁了&#xff0c;我有很多的兴趣比如&#xff1a;跳绳、游泳、看书、写字和玩耍。我 喜欢的东西也很多&#xff1a;水果、蔬菜、大螃蟹、大龙虾。大家要多吃蔬菜少吃油炸食品身体才能强壮、健康。…

visio 画类图时 方法里如何加参数

鼠标双击类(打开属性对话框)-->(类别)操作-->属性-->(类别)参数-->(添加参数)转载于:https://www.cnblogs.com/azhqiang/p/4991907.html