關於互斥量的基本概念:百度百科互斥量
推薦參考博客:秒殺多線程第七篇 經典線程同步 互斥量Mutex
注意:互斥量也是一個內核對象,它用來確保一個線程獨占一個資源的訪問。互斥量與關鍵段的行為非常相似,並且互斥量可以用於不同進程中的線程互斥訪問資源 本文地址
主要用到2個函數:CreateMutex,ReleaseMutex:
CreateMutex
函數功能:創建互斥量(注意與事件Event的創建函數對比)
函數原型:
HANDLE CreateMutex(
LPSECURITY_ATTRIBUTESlpMutexAttributes,
BOOLbInitialOwner,
LPCTSTRlpName
);
第一個參數:表示安全控制,一般直接傳入NULL。
第二個參數:用來確定互斥量的初始擁有者。如果傳入TRUE表示互斥量對象內部會記錄創建它的線程的線程ID號並將遞歸計數設置為1,由於該線程ID非零,所以互斥量處於未觸發狀態。如果傳入FALSE,那么互斥量對象內部的線程ID號將設置為NULL,遞歸計數設置為0,這意味互斥量不為任何線程占用,處於觸發狀態。
第三個參數:用來設置互斥量的名稱,在多個進程中的線程就是通過名稱來確保它們訪問的是同一個互斥量。
返回值:成功則返回一個表示互斥量的句柄,失敗返回NULL。
ReleaseMutex
功能:釋放互斥量
函數原型:
BOOL ReleaseMutex (HANDLEhMutex)
函數說明:
訪問互斥資源前應該要調用等待函數,結束訪問時就要調用ReleaseMutex()來表示自己已經結束訪問,其它線程可以開始訪問了。
另外還有個函數OpenMutex 可以打開其它進程中創建的互斥量
注意:主線程不要忘了刪除互斥量
下面從一個例子說明:假設有三個線程都需要使用打印機,我們可以使用互斥量來控制,這樣就可以保證每次只有一個線程在使用打印機
#include<string>
#include<iostream>
#include<process.h>
#include<windows.h>
using namespace std;
//聲明互斥量句柄
HANDLE hmu;
//線程綁定的函數返回值和參數是確定的,而且一定要__stdcall
unsigned __stdcall threadFun(void *param)
{
WaitForSingleObject(hmu, INFINITE);//等待互斥量
cout<<*(string *)(param)<<endl;
ReleaseMutex(hmu);//釋放互斥量
return 1;
}
int main()
{
//創建互斥量
hmu = CreateMutex(NULL, FALSE, NULL);
HANDLE hth1, hth2, hth3;
string s1 = "first", s2 = "second", s3 = "third";
//創建線程
hth1 = (HANDLE)_beginthreadex(NULL, 0, threadFun, &s1, 0, NULL);
hth2 = (HANDLE)_beginthreadex(NULL, 0, threadFun, &s2, 0, NULL);
hth3 = (HANDLE)_beginthreadex(NULL, 0, threadFun, &s3, 0, NULL);
//等待子線程結束
WaitForSingleObject(hth1, INFINITE);
WaitForSingleObject(hth2, INFINITE);
WaitForSingleObject(hth3, INFINITE);
//一定要記得關閉線程句柄
CloseHandle(hth1);
CloseHandle(hth2);
CloseHandle(hth3);
//千萬別忘了刪除互斥量
CloseHandle(hmu);
}
互斥量有沒有和臨界區一樣具有所有權屬性呢,我們也從相同的例子來看:編寫一個程序,開啟3個線程,這3個線程的ID分別為A、B、C,每個線程將自己的ID在屏幕上打印10遍,要求輸出結果必須按ABC的順序顯示;如:ABCABC….依次遞推。
#include<string>
#include<iostream>
#include<process.h>
#include<windows.h>
using namespace std;
//聲明3個互斥量句柄
HANDLE hmu1, hmu2, hmu3;
//線程綁定的函數返回值和參數是確定的,而且一定要__stdcall
unsigned __stdcall threadFunA(void *)
{
for(int i = 0; i < 10; i++){
WaitForSingleObject(hmu1, INFINITE);//等待互斥量
cout<<"A";
ReleaseMutex(hmu2);//釋放互斥量
}
return 1;
}
unsigned __stdcall threadFunB(void *)
{
for(int i = 0; i < 10; i++){
WaitForSingleObject(hmu2, INFINITE);//等待互斥量
cout<<"B";
ReleaseMutex(hmu3);//釋放互斥量
}
return 2;
}
unsigned __stdcall threadFunC(void *)
{
for(int i = 0; i < 10; i++){
WaitForSingleObject(hmu3, INFINITE);//等待互斥量
cout<<"C";
ReleaseMutex(hmu1);//釋放互斥量
}
return 3;
}
int main()
{
hmu1 = CreateMutex(NULL, FALSE, NULL);
hmu2 = CreateMutex(NULL, FALSE, NULL);
hmu3 = CreateMutex(NULL, FALSE, NULL);
HANDLE hth1, hth2, hth3;
//創建線程
hth1 = (HANDLE)_beginthreadex(NULL, 0, threadFunA, NULL, 0, NULL);
hth2 = (HANDLE)_beginthreadex(NULL, 0, threadFunB, NULL, 0, NULL);
hth3 = (HANDLE)_beginthreadex(NULL, 0, threadFunC, NULL, 0, NULL);
//等待子線程結束
WaitForSingleObject(hth1, INFINITE);
WaitForSingleObject(hth2, INFINITE);
WaitForSingleObject(hth3, INFINITE);
//一定要記得關閉線程句柄
CloseHandle(hth1);
CloseHandle(hth2);
CloseHandle(hth3);
//刪除互斥量
CloseHandle(hmu1);
CloseHandle(hmu2);
CloseHandle(hmu3);
}
從結果看互斥量也具有所有權屬性,即擁有互斥量的線程可以重復進入互斥量保護的區域
【版權聲明】轉載請注明出處:http://www.cnblogs.com/TenosDoIt/p/3601387.html
