用内核对象进行线程同步——互斥量内核对象

互斥内核对象用来确保一个线程独占对一个资源的访问。互斥亮和关键段的的行为完全相同,但关键段是用户模式下的同步对象,意味着互斥量比关键段慢。

内核对象包含一个使用计数(内核对象都有)、线程ID及一个递归计数
线程ID:标识当前占用这个互斥量的是系统中的哪个线程。ID为0,则互斥量不被任何线程占用,处于触发状态;否则处于未触发状态
递归计数:表示这个线程占用互斥量的次数

创建互斥量

// bInitialOwner
// FALSE:互斥量不为任何线程所占用,处于触发状态; 
// TRUE:互斥量被调用线程线程所占用,处于未触发状态
HANDLE CreateMutex(
     LPSECURITY_ATTRIBUTES lpMutexAttributes,
     BOOL bInitialOwner,    
     LPCWSTR lpName
    );

打开互斥量

HANDLE OpenMutex(
     DWORD dwDesiredAccess,
     BOOL bInheritHandle,
     LPCWSTR lpName
    );

释放互斥量

BOOL ReleaseMutex(HANDLE hMutex);

某一个线程一旦成功等到了互斥量(即互斥量处于触发状态),则线程就已经独占了受保护的资源,此时互斥量变为未触发状态,其他任何通过等待该互斥量的线程都不能访问资源。当线程结束时必须调用ReleaseMutex释放互斥量,使互斥量变为触发状态,这样系统会选择一个其他等待该互斥量的线程执行。

互斥量内核对象例子

#include "stdafx.h"
#include <windows.h>          
#include <process.h> 
#include <iostream>

using namespace std;

int g_x = 0;
HANDLE h_Mutex;

// 写入线程
UINT WINAPI ThreadFunc1(PVOID pArguments)
{
    // 互斥量从触发状态变为未触发状态
    // 在等待函数内部,会检测该互斥量的线程ID是否为0,
    // 如果是,即互斥量处于触发状态,则把线程ID设为调用线程的ID,递归计数设为1,此时互斥量处于未触发状态;
    // 如果线程ID是不为0,则线程继续等待
    WaitForSingleObject(h_Mutex, INFINITE);
    int n = 0;
    while (n < 5)
    {
        g_x += n;
        n++;
        cout << "ThreadFunc1.." << endl;
    }
    // 互斥量从未触发状态变为触发状态
    // ReleaseMutex 会把互斥量对象的递归计数减1,
    // 等待了几次,ReleaseMutex 就要调用几次把递归计数变为0,此时线程ID也会设为0,这样就触发了对象。
    ReleaseMutex(h_Mutex);
    _endthreadex(0);
    return 0;
}
// 读线程
UINT WINAPI ThreadFunc2(PVOID pArguments)
{
    WaitForSingleObject(h_Mutex, INFINITE);
    cout << "ThreadFunc2.." << endl;
    ReleaseMutex(h_Mutex);
    _endthreadex(0);
    return 0;
}
// 写入线程
UINT WINAPI ThreadFunc3(PVOID pArguments)
{
    WaitForSingleObject(h_Mutex, INFINITE);
    int n = 0;
    while (n < 5)
    {
        g_x += n;
        n++;
        cout << "ThreadFunc3.." << endl;
    }
    ReleaseMutex(h_Mutex);
    _endthreadex(0);
    return 0;
}

int _tmain(int argc, _TCHAR* argv[])
{
    HANDLE   handle[3];
    unsigned    unThreadID[3];

    cout << "g_x initial value: " << g_x << endl;
    // 创建一个处于触发状态的互斥量
    h_Mutex = CreateMutex(NULL, FALSE, _T("Thread_Mutex"));
    handle[0] = (HANDLE)_beginthreadex(NULL,
        0,
        &ThreadFunc1,
        NULL,
        0,
        &unThreadID[0]);
    handle[1] = (HANDLE)_beginthreadex(NULL,
        0,
        &ThreadFunc2,
        NULL,
        0,
        &unThreadID[1]);
    handle[2] = (HANDLE)_beginthreadex(NULL,
        0,
        &ThreadFunc3,
        NULL,
        0,
        &unThreadID[2]);

    g_x = 100;
    cout << "g_x Final value: " << g_x << endl;
    getchar();
    CloseHandle(h_Mutex);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值