线程同步 互斥量 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(只适用于互斥量)。

鸣谢

觉的我写的帮帮哒, 发个红包赏赏赏

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值