C++多线程同步之临界区(CriticalSection)


原文链接:http://blog.csdn.net/olansefengye1/article/details/53262917

一、Win32平台

1、相关头文件和接口

#include <windows.h> CRITICAL_SECTION cs;//定义临界区对象 InitializeCriticalSection(&cs);//初始化临界区 EnterCriticalSection(&cs);//进入临界区 LeaveCriticalSection(&cs);//离开临界区 DeleteCriticalSection(&cs);//删除临界区

2、Win32源码

//=====================MyCriticalSection.h=========================== #ifndef _My_CRITICAL_SECTION_H #define _My_CRITICAL_SECTION_H #include <windows.h> //对临界区同样进行封装 class CMyCriticalSection { public: CMyCriticalSection() { InitializeCriticalSection(&m_cSection); } void Lock() { EnterCriticalSection(&m_cSection); } void UnLock() { LeaveCriticalSection(&m_cSection); } //利用析构函数删除临界区对象 virtual ~CMyCriticalSection() { DeleteCriticalSection(&m_cSection); } private: CRITICAL_SECTION m_cSection; }; class CCriticalSectionAutoLock { public: //利用构造函数上锁,即进去临界区 CCriticalSectionAutoLock(CMyCriticalSection *mySection) :pCMySection(mySection) { pCMySection->Lock(); } //利用析构函数解锁,即离开临界区 virtual ~CCriticalSectionAutoLock() { pCMySection->UnLock(); } private: CMyCriticalSection *pCMySection; }; #endif
#include <iostream> #include <windows.h> #include "MySemaphore.h" #include "MyMutex.h" #include "MyCriticalSection.h" using namespace std; //HANDLE g_hSemaphore = NULL; //HANDLE g_hMutex = NULL; CMySemaphore MySemaphore; //信号量 CMyMutex MyMutex; //互斥量 CMyCriticalSection MyCriticalSection; //临界区 DWORD WINAPI Fun(LPVOID lpParamter) { string strPrint((const char*)lpParamter); int iRunTime = 0; //执行100次跳出 while(++iRunTime<10) { { CCriticalSectionAutoLock cLock(&MyCriticalSection); cout <<"["<< iRunTime <<"]:"<< strPrint.c_str()<<endl; } Sleep(1); //若去掉此句 可能导致其他线程无法进入临界区,因为 cLock在这之前析构,离开临界区 } return 0; } int main() { //创建五个子线程 string str1 = "A"; string str2 = "B"; string str3 = "C"; string str4 = "D"; string str5 = "E"; HANDLE hThread1 = CreateThread(NULL, 0, Fun, (void*)str1.c_str(), 0, NULL); HANDLE hThread2 = CreateThread(NULL, 0, Fun, (void*)str2.c_str(), 0, NULL); HANDLE hThread3 = CreateThread(NULL, 0, Fun, (void*)str3.c_str(), 0, NULL); HANDLE hThread4 = CreateThread(NULL, 0, Fun, (void*)str4.c_str(), 0, NULL); HANDLE hThread5 = CreateThread(NULL, 0, Fun, (void*)str5.c_str(), 0, NULL); //关闭线程 CloseHandle(hThread1); CloseHandle(hThread2); CloseHandle(hThread3); CloseHandle(hThread4); CloseHandle(hThread5); getchar(); // system("pause"); return 0; }

执行结果:这里写图片描述 
这是加上Sleep(1);的运行结果,没有加上Sleep(1);的执行结果如下: 
这里写图片描述 
从结果我们可以看出如果没有加上Sleep(1),即在离开临界区后进行休眠,其他线程进入临界区的概率会大大降低,原因可能是由于While循环在不停的循环时,其他线程还没有那么快能够进入临界区,因此在这种情况下想让所有的线程都有机会进入临界区,则需要在离开临界区之后做短暂休眠即可。

3、Linux平台

在Linux环境下,没有Windows下的临界区的概念,但是也可以利用互斥量实现该功能。Linux下的API如下,在前面的博文里也有讲到过,可以参考http://blog.csdn.net/olansefengye1/article/details/53086141

include <pthread.h> int pthread_mutexattr_init(pthread_mutexattr_t *attr); /*初始化函数*/ int pthread_mutexattr_destroy(pthread_mutexattr_t *attr);/*去初始化函数*/ int pthread_mutex_lock(pthread_mutexattr_t *attr)/*加锁*/ int pthread_mutex_unlock(pthread_mutexattr_t *attr)/*解锁*/

但是两者并不是完全一样的,他们的区别总结如下: 
1、临界区只能用于对象在同一进程里线程间的互斥访问;互斥体可以用于对象进程间或线程间的互斥访问。 
2、临界区是非内核对象,只在用户态进行锁操作,速度快;互斥体是内核对象,在核心态进行锁操作,速度慢。 
3、临界区和互斥体在Windows平台都下可用;Linux下只有互斥体可用。 
4、临界区:通过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问。 
5、互斥量:为协调共同对一个共享资源的单独访问而设计的。


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM