原文鏈接: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、互斥量:為協調共同對一個共享資源的單獨訪問而設計的。