windows多執行緒同步--互斥量

tenos發表於2014-03-14

關於互斥量的基本概念:百度百科互斥量

推薦參考部落格:秒殺多執行緒第七篇 經典執行緒同步 互斥量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);
}

 

image

從結果看互斥量也具有所有權屬性,即擁有互斥量的執行緒可以重複進入互斥量保護的區域

 

【版權宣告】轉載請註明出處http://www.cnblogs.com/TenosDoIt/p/3601387.html

相關文章