線程同步 信號量 Semaphore 內核對象 CreateSemaphore

0、思考

生產者消費者問題,同步互斥問題,有界緩衝器問題:
1、兩個進程對同一個內存資源操作,一個生產者,一個消費者;
2、生產者往共享內存資源填充數據,如果區域滿,則等待消費者消費數據;
3、消費者從共享內存資源取數據,如果區域空,則等待生產者填充數據;
4、生產者的填充數據行爲和消費者的消費數據行爲不可在同一時間發生。

1、相關api

CreateSemaphore
CreateSemaphoreEx
OpenSemaphore
ReleaseSemaphore
CloseHandle
WaitForSingleObject
WaitForMultipleObjects

2、寫在前面

// 生產者消費者問題,同步互斥問題,有界緩衝器問題:
// 互斥量mutex控制兩者不能同時操作緩存區;信號量empty和full表示緩存區的空槽數量和滿槽數量;
// mutex初始爲1,empty初始爲n;full初始爲0;
// P、V(wait、signal)(down、up)(測試、增加)(-1、+1);
// 生產者
void Productor() {
    while(1) {
        P(&empty);
        p(&mutex);

        V(&mutex);
        V(&full);
    }
}

// 消費者
void Consumer() {
    while(1) {
        P(&full);
        P(&mutex);

        V(&mutex);
        V(&empty);
    }
}

3、api說明

// 創建信號量內核對象
// lpSemaphoreAttributes:安全屬性。(通常爲NULL)
// lInitialCount:資源中一開始有多少可供使用
// lMaximumCount:應用程序能夠處理的最大資源數
// lpName:內核對象名稱
WINBASEAPI
__out_opt
HANDLE
WINAPI
CreateSemaphoreA(
    __in_opt LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
    __in     LONG lInitialCount,
    __in     LONG lMaximumCount,
    __in_opt LPCSTR lpName
);
WINBASEAPI
__out_opt
HANDLE
WINAPI
CreateSemaphoreW(
    __in_opt LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
    __in     LONG lInitialCount,
    __in     LONG lMaximumCount,
    __in_opt LPCWSTR lpName
);
#ifdef UNICODE
#define CreateSemaphore  CreateSemaphoreW
#else
#define CreateSemaphore  CreateSemaphoreA
#endif // !UNICODE

// dwFlags:系統保留,設定爲0。
// dwDesiredAccess:訪問權限。(通常爲SEMAPHORE_ALL_ACCESS)
WINBASEAPI
__out_opt
HANDLE
WINAPI
CreateSemaphoreExA(
    __in_opt    LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
    __in        LONG lInitialCount,
    __in        LONG lMaximumCount,
    __in_opt    LPCSTR lpName,
    __reserved  DWORD dwFlags,
    __in        DWORD dwDesiredAccess
);
WINBASEAPI
__out_opt
HANDLE
WINAPI
CreateSemaphoreExW(
    __in_opt    LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
    __in        LONG lInitialCount,
    __in        LONG lMaximumCount,
    __in_opt    LPCWSTR lpName,
    __reserved  DWORD dwFlags,
    __in        DWORD dwDesiredAccess
);
#ifdef UNICODE
#define CreateSemaphoreEx  CreateSemaphoreExW
#else
#define CreateSemaphoreEx  CreateSemaphoreExA
#endif // !UNICODE

// 增加信號量的當前資源計數。
// hSemaphore:指定內核對象
// lReleaseCount:表示增加個數,必須大於0且不超過最大資源數量。
// lpPreviousCount:當前資源計數,設爲NULL表示不需要傳出。(通常爲NULL)(PS:沒有辦法在不改變當前資源計數的前提下得到當前值)
WINBASEAPI
BOOL
WINAPI
ReleaseSemaphore(
    __in      HANDLE hSemaphore,
    __in      LONG lReleaseCount,
    __out_opt LPLONG lpPreviousCount
);

// dwDesiredAccess:訪問權限。(通常爲SEMAPHORE_ALL_ACCESS)
// bInheritHandle:信號量繼承性。通常爲true)
// lpName:內核對象名稱。
WINBASEAPI
__out_opt
HANDLE
WINAPI
OpenSemaphoreA(
    __in DWORD dwDesiredAccess,
    __in BOOL bInheritHandle,
    __in LPCSTR lpName
);
WINBASEAPI
__out_opt
HANDLE
WINAPI
OpenSemaphoreW(
    __in DWORD dwDesiredAccess,
    __in BOOL bInheritHandle,
    __in LPCWSTR lpName
);
#ifdef UNICODE
#define OpenSemaphore  OpenSemaphoreW
#else
#define OpenSemaphore  OpenSemaphoreA
#endif // !UNICODE

4、C++封裝

#pragma once

#include <windows.h>


class ncSemaphore
{
public:
    ncSemaphore(LONG lInitialCount = 1, LONG lMaximumCount = 1, LPCTSTR lpName = NULL)
    {
        _sem = CreateSemaphore(NULL, lInitialCount, lMaximumCount, lpName);
    }

    ~ncSemaphore()
    {
        CloseHandle(_sem);
    }

public:
    DWORD wait(DWORD timeout = INFINITE)
    {
        return WaitForSingleObject (_sem, timeout);
    }

    BOOL release (LONG lReleaseCount = 1, LPLONG lpPreviousCount = NULL)
    {
        return ReleaseSemaphore(_sem, lReleaseCount, lpPreviousCount);
    }

private:
    HANDLE _sem;
};

5、順藤摸瓜

讀者寫者問題,同步互斥問題
哲學家進餐問題,同步互斥問題
放水果問題
讀文件問題
閱覽室問題
單行道問題
理髮師問題

鳴謝

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章