PoEdu培训 Windows班 第三十九课 Windows 内核对象(六) 信号量和互斥体
文章类别: 培训笔记 0 评论

PoEdu培训 Windows班 第三十九课 Windows 内核对象(六) 信号量和互斥体

文章类别: 培训笔记 0 评论

Windows 内核对象(六) 信号量和互斥体

信号量

我们有时候, 会有控制程序的启动次数的需求
这就用到我们的信号量(Semaphore)内核对象.
可以使用CreateSemaphore创建一个信号量
也可以使用OpenSemaphore打开一个信号量

CreateSemaphore

HANDLE WINAPI CreateSemaphore(
  _In_opt_ LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
  _In_     LONG                  lInitialCount,
  _In_     LONG                  lMaximumCount,
  _In_opt_ LPCTSTR               lpName
);

lpSemaphoreAttributes

lInitialCount

lMaximumCount

lpName

示例

#include <Windows.h>
#include <tchar.h>


INT _tmain()
{
    // ==============================================================
    {
        // 初始计数为0, 最大计数为5
        HANDLE hSemaphore = CreateSemaphore(NULL, 0, 5, TEXT("HadesSem"));
        // OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE, TEXT("HadesSem"));
        // 此时, 因为计数是 0 , 所以程序被阻塞
        WaitForSingleObject(hSemaphore, INFINITE);
        CloseHandle(hSemaphore);
    }
    // ==============================================================

    // ==============================================================
    {
        // 初始计数为0, 最大计数为5
        HANDLE hSemaphore = CreateSemaphore(NULL, 2, 5, TEXT("HadesSem"));
        WaitForSingleObject(hSemaphore, INFINITE);
        WaitForSingleObject(hSemaphore, INFINITE);
        // 此时, 因为计数是 2 , 所以程序被阻塞
        WaitForSingleObject(hSemaphore, INFINITE);
        CloseHandle(hSemaphore);
    }
    // ==============================================================

    // ==============================================================
    {
        // 初始计数为0, 最大计数为5
        HANDLE hSemaphore = CreateSemaphore(NULL, 2, 5, TEXT("HadesSem"));
        // 使用ReleaseSemaphore来释放/增加计数
        // 最后一个参数是输出参数, 输出累加之前的数
        // 现在是初始2个计数, 累加2个, 所以现在是4个计数
        ReleaseSemaphore(hSemaphore, 2, NULL);
        WaitForSingleObject(hSemaphore, INFINITE);
        WaitForSingleObject(hSemaphore, INFINITE);
        WaitForSingleObject(hSemaphore, INFINITE);
        WaitForSingleObject(hSemaphore, INFINITE);
        // 此时, 因为计数是 4 , 所以程序被阻塞
        WaitForSingleObject(hSemaphore, INFINITE);
        CloseHandle(hSemaphore);
    }
    // ==============================================================

    // ==============================================================
    {
        // 初始计数为0, 最大计数为5
        HANDLE hSemaphore = CreateSemaphore(NULL, 2, 5, TEXT("HadesSem"));
        // 使用ReleaseSemaphore来释放/增加计数
        // 最后一个参数是输出参数, 输出累加之前的数
        // 现在是初始2个计数, 累加4个, 所以现在是6个计数
        // 但是我们最大是 5个 所以函数执行失败
        // 计数还是2
        ReleaseSemaphore(hSemaphore, 4, NULL);
        WaitForSingleObject(hSemaphore, INFINITE);
        WaitForSingleObject(hSemaphore, INFINITE);
        // 此时, 因为计数是 2 , 所以程序被阻塞
        WaitForSingleObject(hSemaphore, INFINITE);
        CloseHandle(hSemaphore);
    }
    // ==============================================================

    return 0;
}

互斥体

在互斥体内核对象中, 会有一个线程ID

CreateMutex

HANDLE WINAPI CreateMutex(
  _In_opt_ LPSECURITY_ATTRIBUTES lpMutexAttributes,
  _In_     BOOL                  bInitialOwner,
  _In_opt_ LPCTSTR               lpName
);

lpMutexAttributes

bInitialOwner

lpName

创建时设置拥有者的示例

#include <Windows.h>
#include <process.h>
#include <tchar.h>

HANDLE g_hMutex = INVALID_HANDLE_VALUE;

UINT WINAPI ThreadFunc(LPVOID lParam)
{
    while (WaitForSingleObject(g_hMutex, INFINITE) == WAIT_OBJECT_0)
        _tprintf(TEXT("Thread is runing....\n"));
    return 0;
}

INT _tmain()
{
    // 无信号的互斥体
    g_hMutex = CreateMutex(NULL, TRUE, NULL);
    // 这里将不会阻塞
    // 因为, 我们当前线程是创建互斥体的线程
    // 它拥有了当前互斥体的所有权限
    // 无论怎么Wait, 都不会阻塞
    WaitForSingleObject(g_hMutex, INFINITE);
    WaitForSingleObject(g_hMutex, INFINITE);
    WaitForSingleObject(g_hMutex, INFINITE);
    WaitForSingleObject(g_hMutex, INFINITE);
    WaitForSingleObject(g_hMutex, INFINITE);
    WaitForSingleObject(g_hMutex, INFINITE);


    HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, ThreadFunc, NULL, 0, NULL);
    // 释放互斥体
    // 不释放, 线程将等待
    // 注释掉下面一句代码观察情况
    ReleaseMutex(g_hMutex);
    WaitForSingleObject(hThread, INFINITE);

    return 0;
}

创建时不设置拥有者的示例

等待一次的互斥体

#include <Windows.h>
#include <process.h>
#include <tchar.h>

HANDLE g_hMutex2 = INVALID_HANDLE_VALUE;

UINT WINAPI ThreadFunc2(LPVOID lParam)
{
    while (WaitForSingleObject(g_hMutex2, INFINITE) == WAIT_OBJECT_0)
        _tprintf(TEXT("Thread is runing....\n"));
    return 0;
}

INT _tmain()
{
    // 有信号的互斥体
    g_hMutex2 = CreateMutex(NULL, FALSE, NULL);
    // 这里将不会阻塞
    WaitForSingleObject(g_hMutex2, INFINITE);
    // 但是在之后, 我们的互斥体就会阻塞了
    // 所以要进行Release
    ReleaseMutex(g_hMutex2);

    HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, ThreadFunc2, NULL, 0, NULL);
    WaitForSingleObject(hThread, INFINITE);

    return 0;
}

等待多次的互斥体

#include <Windows.h>
#include <process.h>
#include <tchar.h>

HANDLE g_hMutex2 = INVALID_HANDLE_VALUE;

UINT WINAPI ThreadFunc2(LPVOID lParam)
{
    while (WaitForSingleObject(g_hMutex2, INFINITE) == WAIT_OBJECT_0)
        _tprintf(TEXT("Thread is runing....\n"));
    return 0;
}

INT _tmain()
{
    // 有信号的互斥体
    g_hMutex2 = CreateMutex(NULL, FALSE, NULL);
    // 这里将不会阻塞
    WaitForSingleObject(g_hMutex2, INFINITE);
    WaitForSingleObject(g_hMutex2, INFINITE);
    WaitForSingleObject(g_hMutex2, INFINITE);
    WaitForSingleObject(g_hMutex2, INFINITE);
    WaitForSingleObject(g_hMutex2, INFINITE);
    // 但是在之后, 我们的互斥体就会阻塞了
    // 所以要进行Release
    // 我们Wait了多次, 所以要Release相应次数
    ReleaseMutex(g_hMutex2);
    ReleaseMutex(g_hMutex2);
    ReleaseMutex(g_hMutex2);
    ReleaseMutex(g_hMutex2);
    ReleaseMutex(g_hMutex2);
    ReleaseMutex(g_hMutex2);

    HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, ThreadFunc2, NULL, 0, NULL);
    WaitForSingleObject(hThread, INFINITE);

    return 0;
}

未完待续...

如有错误,请提出指正!谢谢.

回复