C++多线程之使用Mutex和Critical_Section

Mutex和Critical Section都是主要用于限制多线程(Multithread)对全局或共享的变量、对象或内存空间的访问。下面是其主要的异同点(不同的地方用绿色表示)。


Mutex


Critical Section


性能和速度


慢。

Mutex 是内核对象,相关函数的执行 (WaitForSingleObject,

ReleaseMutex)需要用户模式(User Mode)到内核模式

(Kernel Mode)的转换,在x86处理器上这种转化一般要

发费600个左右的 CPU指令周期。


快。

Critical Section本身不是内核对象,相关函数

(EnterCriticalSection,LeaveCriticalSection)

的调用一般都在用户模式内执行,在x86处理器上

一般只需要发费9个左右的 CPU指令周期。只有

当想要获得的锁正好被别的线程拥有时才会退化

成和Mutex一样,即转换到内核模式,发费600个

左右的 CPU指令周期。


能否跨越进程(Process)边界


可以


不可


定义写法


HANDLE hmtx;


CRITICAL_SECTION cs;


初始化写法


hmtx= CreateMutex (NULL, FALSE, NULL);


InitializeCriticalSection(&cs);


结束清除写法


CloseHandle(hmtx);


DeleteCriticalSection(&cs);


无限期等待的写法


WaitForSingleObject (hmtx, INFINITE);


EnterCriticalSection(&cs);


0等待(状态检测)的写法


WaitForSingleObject (hmtx, 0);


TryEnterCriticalSection(&cs);


任意时间等待的写法


WaitForSingleObject (hmtx, dwMilliseconds);


不支持


锁释放的写法


ReleaseMutex(hmtx);


LeaveCriticalSection(&cs);


能否被一道用于等待其他内核对象


可以(使用WaitForMultipleObjects,

WaitForMultipleObjectsEx,

MsgWaitForMultipleObjects,

MsgWaitForMultipleObjectsEx等等)


不可


当拥有锁的线程死亡时


Mutex变成abandoned状态,其他的等待线程可以获得锁。


Critical Section的状态不可知(undefined),

以后的动作就不能保证了。


自己会不会锁住自己


不会(对已获得的Mutex,重复调用WaitForSingleObject不会

锁住自己。但最后你别忘了要调用同样次数的

ReleaseMutex)


不会(对已获得的Critical Section,重复调用

EnterCriticalSection不会锁住自己。但最后

你别忘了要调用同样次数的

LeaveCriticalSection)

下面是一些补充:

l         请先检查你的设计,把不必要的全局或共享对象改为局部对象。全局的东西越少,出问题的可能就越小。

l         每次你使用EnterCriticalSection时,请不要忘了在函数的所有可能返回的地方都加上LeaveCriticalSection。对于Mutex也同样。若你把这个问题和Win32 structured exception或C++ exception一起考虑,你会发现问题并不是那么简单。自定义一个封装类可能是一种解决方案,以Critical Section为例的代码如下所示:

class csholder

{

CRITICAL_SECTION *cs;

public:

csholder(CRITICAL_SECTION *c): cs(c)

{ EnterCriticalSection(cs); }

~csholder() { LeaveCriticalSection(cs); }

};

CRITICAL_SECTION some_cs;

void foo()

{

// ...

csholder hold_some(&some_cs);

// ... CS protected code here

// at return or if an exception happens

// hold_some‘s destructor is automatically called

}

l         根据你的互斥范围需求的不同,把Mutex或Critical Section定义为类的成员变量,或者静态类变量。

l         若你想限制访问的全局变量只有一个而且类型比较简单(比如是LONG或PVOID型),你也可以使用InterlockedXXX系列函数来保证一个线程写多个线程读。

Demo程序

#include <Windows.h>

#include <iostream>

using namespace std;

int index = 0;

// 临界区结构对象
CRITICAL_SECTION g_cs;

HANDLE hMutex = NULL;

void changeMe()
{
 cout << index++ << endl;
}

void changeMe2()
{
 cout << index++ << endl;
}
void changeMe3()
{
 cout << index++ << endl;
}

DWORD WINAPI th1(LPVOID lpParameter)
{
 while(1)
 {
  Sleep(1600); //sleep 1.6 s
  // 进入临界区
  EnterCriticalSection(&g_cs);

// 等待互斥对象通知
  //WaitForSingleObject(hMutex, INFINITE);

// 对共享资源进行写入操作
  //cout << "a" << index++ << endl;
  changeMe();
  changeMe2();
  changeMe3();

// 释放互斥对象
  //ReleaseMutex(hMutex);

// 离开临界区
  LeaveCriticalSection(&g_cs);  
 }
 return 0;
}

DWORD WINAPI th2(LPVOID lpParameter)
{
 while(1)
 {
  
  Sleep(2000); //sleep 2 s
  // 进入临界区
  EnterCriticalSection(&g_cs);

// 等待互斥对象通知
  //WaitForSingleObject(hMutex, INFINITE);

//cout << "b" << index++ << endl;
  changeMe();
  changeMe2();
  changeMe3();

// 释放互斥对象
  //ReleaseMutex(hMutex);

// 离开临界区
  LeaveCriticalSection(&g_cs); 
 }
 return 0;
}

int main(int argc, char* argv[])
{
 // 创建互斥对象
 //hMutex = CreateMutex(NULL, TRUE, NULL);
 // 初始化临界区
 InitializeCriticalSection(&g_cs);

HANDLE hThread1;
 HANDLE hThread2;
 hThread1 = CreateThread(NULL, 0, th1,  NULL, 0, NULL);
 hThread2 = CreateThread(NULL, 0, th2,  NULL, 0, NULL);
 int k; 
 cin >> k; 
 printf("Hello World!\n");
 return 0;
}

C++多线程之使用Mutex和Critical_Section

时间: 2024-10-12 16:09:21

C++多线程之使用Mutex和Critical_Section的相关文章

mutex和CRITICAL_SECTION,互斥和临界区

本文不没有任何知识可讲,只是帖上自己测试的结果. 想看底层原理的可以直接关闭. 不过对于急着要选方案的人,倒提供一些帮助. 先说一些无关紧要的废话: ==================================================================================================================================================== 先说说为什么会有这篇文章. 我在做练习的时候,参考一

C# 多线程(lock,Monitor,Mutex,同步事件和等待句柄)

本文来自:http://www.cnblogs.com/SkySoot/archive/2012/04/02/2430295.html 本篇从 Monitor,Mutex,ManualResetEvent,AutoResetEvent,WaitHandler 的类关系图开始,希望通过本篇的介绍能对常见的线程同步方法有一个整体的认识,而对每种方式的使用细节,适用场合不会过多解释. 让我们来看看这几个类的关系图: 1. lock 关键字     lock 是 C# 关键词,它将语句块标记为临界区,确

C# 多线程系列之Mutex使用

互斥量是一个内核对象,它用来确保一个线程独占一个资源的访问,并且互斥量可以用于不同进程中的线程互斥访问资源. 我们可以把Mutex看作一个出租车,乘客看作线程.乘客首先等车,然后上车,最后下车.当一个乘客在车上时,其他乘客就只有等他下车以后才可以上车.而线程与C# Mutex对象的关系也正是如此,线程使用Mutex.WaitOne()方法等待C# Mutex对象被释放,如果它等待的C# Mutex对象被释放了,或者它没有被任何对象有用,它就自动拥有这个对象,直到它调用Mutex.ReleaseM

VC++多线程同步(一) Mutex互斥量

一 .同步机制的引入目的是为了解决三个主要问题 1为了控制线程之间共享资源的同步访问,保证共享资源的完整性.(比如一个线程正在更新一个数据,而另外一个线程正在读取该数据,那么就不知道该数据是新的还是旧的,为了避免这种状况的发生) 2确保线程之间的动作,以制定的次序发送,例如一个线程的触发,需要另外一个线程的结果,作为条件. 3为了控制某一个共享资源的最大访问量,例如我们同时只能处理5个客户的请求,这时候,我们需要放到队列进行等待. 二.同步概念就是等待 WIN32  提供了API 等待函数 DW

c++多线程基础3(mutex)

互斥锁 互斥算法避免多个线程同时访问共享资源.这会避免数据竞争,并提供线程间的同步支持.定义于头文件 <mutex> 互斥锁有可重入.不可重入之分.C++标准库中用 mutex 表示不可重入的互斥锁,用 recursive_mutex 表示可重入的互斥锁.为这两个类增加根据时间来阻塞线程的能力,就又有了两个新的互斥锁:timed_mutex(不可重入的锁).recursive_timed_mutex(可重入的锁) C++标准库的所有mutex都是不可拷贝的,也不可移动 std::mutex:

Delphi多线程编程(10)--多线程同步之Mutex(互斥对象)

原理分析: 互斥对象是系统内核对象,各个线程都可以拥有它,谁拥有它谁就可以执行 执行完毕,用ReleaseMutex 函数释放拥有权,以让其他等待的线程可以使用 其他线程可以使用 WaitForSingleObject函数排队等待(等待也可以理解为排队申请) 使用过程 var hMutex: THandle; {应该先声明一个全局的互斥句柄} CreateMutex {建立互斥对象} WaitForSingleObject {用等待函数排队等候} ReleaseMutex {释放拥有权} Clo

【转】用C++实现多线程Mutex锁(Win32)

原作者:chexlong 原文地址:http://blog.csdn.net/chexlong/article/details/7051193 本文目的:用C++和Windows的互斥对象(Mutex)来实现线程同步锁. 准备知识:1,内核对象互斥体(Mutex)的工作机理,WaitForSingleObject函数的用法,这些可以从MSDN获取详情: 2,当两个或更多线程需要同时访问一个共享资源时,系统需要使用同步机制来确保一次只有一个线程使用该资源.Mutex 是同步基元,它只向一个线程授予

windows下使用Critical Section和Mutex实现线程同步实例

利用critical section 和 Mutex两种不同的线程同步的方法实现生产者消费者问题.生产者线程要能够对一个计数器进行增的操作,并且将其输出在控制台上,消费者线程能够对这个计数器进行减的操作,并将其输出在控制台上.两种线程都共享一个计数器. 其中增.减计数器的数我设置为1-6随机. 测试两种方法的对比,用网上整理出的一张表如下 1.使用CriticalSection 方法时,有一个临界区cs 在将临界区传递给 InitializeCriticalSection 时(或者更准确地说,是

浅解多线程(二)之和尚们的那些事儿

浅解多线程(一)之线程入门起步 本文链接 确定多线程的结束时间,thread的IsAlive属性 线程优先级,thread的ThreadPriority属性 线程通信之Monitor类 线程排队之Join 多线程互斥锁Mutex 信号量semaphore 确定多线程的结束时间,thread的IsAlive属性 在多个线程运行的背景下,了解线程什么时候结束,什么时候停止是很有必要的. 案例:老和尚念经计时,2本经书,2个和尚念,一人一本,不能撕破,最短时间念完,问老和尚们念完经书最短需要多长时间.