1. 程式人生 > >執行緒同步 互斥量 Mutex 核心物件 CreateMutex

執行緒同步 互斥量 Mutex 核心物件 CreateMutex

0、思考

1、相關api

CreateMutex
CreateMutexEx
OpenMutex
ReleaseMutex
CloseHandle
WaitForSingleObject
WaitForMultipleObjects

2、寫在前面

互斥量:確保一個執行緒獨佔對一個資源的訪問。(與關鍵程式碼段行為完全相同,只是互斥量屬於核心物件,關鍵程式碼段屬於使用者模式下的同步物件)
互斥量包含一個使用計數、執行緒id以及一個遞迴計數。(後面有用)
異常:假設執行緒試圖等待一個未觸發的互斥量物件。在這種情況下,執行緒通常會進入等待狀態。但是,系統要檢查想要獲取互斥物件的執行緒ID是否與互斥
    物件內部記錄的執行緒ID相同。如果兩個執行緒ID相同,即使互斥物件處於未通知狀態,系統也允許該執行緒保持可排程狀態。

3、api說明

// 
// lpMutexAttributes:安全屬性。(通常為NULL)
// bInitialOwner:互斥量初始狀態;觸發狀態(false),互斥量物件的執行緒id和遞迴計數都是0,不被任何執行緒佔用;未觸發狀態(true),物件執行緒
    id將被設為呼叫執行緒的執行緒id,遞迴計數將被設為1。(通常為false)
// lpName:核心物件名稱
WINBASEAPI
__out_opt
HANDLE
WINAPI
CreateMutexA(
    __in_opt LPSECURITY_ATTRIBUTES lpMutexAttributes,
    __in     BOOL bInitialOwner,
    __in_opt LPCSTR lpName
);
WINBASEAPI
__out_opt
HANDLE
WINAPI
CreateMutexW(
    __in_opt LPSECURITY_ATTRIBUTES lpMutexAttributes,
    __in     BOOL bInitialOwner,
    __in_opt LPCWSTR lpName
);
#ifdef UNICODE
#define CreateMutex  CreateMutexW
#else
#define CreateMutex  CreateMutexA
#endif // !UNICODE

// dwFlags:0表示bInitialOwner的false,CREATE_MUTEX_INITIAL_OWNER表示true
// dwDesiredAccess:訪問許可權
WINBASEAPI
__out_opt
HANDLE
WINAPI
CreateMutexExA(
    __in_opt LPSECURITY_ATTRIBUTES lpMutexAttributes,
    __in_opt LPCSTR lpName,
    __in     DWORD dwFlags,
    __in     DWORD dwDesiredAccess
);
WINBASEAPI
__out_opt
HANDLE
WINAPI
CreateMutexExW(
    __in_opt LPSECURITY_ATTRIBUTES lpMutexAttributes,
    __in_opt LPCWSTR lpName,
    __in     DWORD dwFlags,
    __in     DWORD dwDesiredAccess
);
#ifdef UNICODE
#define CreateMutexEx  CreateMutexExW
#else
#define CreateMutexEx  CreateMutexExA
#endif // !UNICODE

// 釋放互斥量。
// hMutex:核心物件控制代碼
WINBASEAPI
BOOL
WINAPI
ReleaseMutex(
    __in HANDLE hMutex
);

// 訪問互斥量物件。(當訪問權執行緒不再需要訪問資源時,必須呼叫)
// dwDesiredAccess:訪問許可權。(通常為SEMAPHORE_ALL_ACCESS)
// bInheritHandle:繼承性。(通常為false)
// lpName:核心物件名稱。
WINBASEAPI
__out_opt
HANDLE
WINAPI
OpenMutexA(
    __in DWORD dwDesiredAccess,
    __in BOOL bInheritHandle,
    __in LPCSTR lpName
);
WINBASEAPI
__out_opt
HANDLE
WINAPI
OpenMutexW(
    __in DWORD dwDesiredAccess,
    __in BOOL bInheritHandle,
    __in LPCWSTR lpName
);
#ifdef UNICODE
#define OpenMutex  OpenMutexW
#else
#define OpenMutex  OpenMutexA
#endif // !UNICODE

4、C++封裝

#pragma once

#include <windows.h>


class ncMutex
{
public:
    ncMutex(LPCTSTR lpName = NULL)
    {
        _mutex = CreateMutex(NULL, False, lpName);
    }

    ~ncMutex()
    {
        CloseHandle(_mutex);
    }

public:
    DWORD lock (DWORD timeout = INFINITE)
    {
        return WaitForSingleObject
(_mutex, timeout); } BOOL unlock () { return ReleaseMutex(_mutex); } private: HANDLE _mutex; };

5、順藤摸瓜

執行緒所有權:除了互斥量,沒有任何一個會記住自己是哪個執行緒等待成功的核心物件。(這使得在未觸發狀態下,也能為執行緒所獲得)
遺棄:如果佔用互斥量執行緒在釋放互斥量之前終止(使用ExitThread、TerminateThread、ExitProcess、TerminateProcess),由於佔用互斥量的執行緒
    已經終止,因此無法釋放它。
因為系統會記錄所有的互斥量和執行緒核心物件,因此它確切知道互斥量何時被遺棄。當互斥量被遺棄時,系統會自動將互斥量物件的執行緒id和計數設為0,
    然後檢查有沒有其他執行緒等待該互斥量。如果有,那麼系統會公平的選中一個正在等待的執行緒,把物件內部執行緒id設為所選執行緒id,計數設為1,這樣
    被選擇執行緒變成可排程狀態,只是等待函式在此種情況返回WAIT_ABANDONED(只適用於互斥量)。

鳴謝

覺的我寫的幫幫噠, 發個紅包賞賞賞