2021-03-15Win3200
请注意,本文编写于 624 天前,最后修改于 204 天前,其中某些信息可能已经过时。

目录


1. 内核级临界资源怎么办?

上节课的内容仅仅能够保证同一个进程中的多个线程安全,但无法保证内核级(可以跨进程共享)临界资源的安全问题
内核级临界资源

要把临界资源放到内核里,互斥体就是能够放在内核中的临界资源

2. 互斥体的使用

互斥体

A进程中的某个线程,要访问内核级的临界资源时,首先要访问0环的互斥体,如果能访问就可以对临界资源进行操作,
此时另外的进程B中的线程要访问内核级的临界资源,也要取获取0环的互斥体,这个时候如果令牌时被占用,那么就无法对临界资源进行操作

c
HANDLE CreateMutex(
    LPSECURITY_ATTRIBUTES lpMutexAttributes,
    // 指向安全属性的指针
    BOOL bInitialOwner,
    // 初始化互斥体的所有者,一创建出来互斥体就能用,也就是有信号,就填FALSE,没有信号就填TRUE
    LPCTSTR lpName
    // 指向互斥体的指针
 );
c
# include <windows.h>

int main()
{
    //创建一个互斥体
    HANDLE g_hMutex = CreateMutex(NULL,FALSE,"XYZ");
    //获取令牌,以后信号,线程的拥有者
    WaitForSingleObject(g_hMutex,INFINITE);
    //操作资源
    for(int i = 0; i < 10; i++)
    {
        Sleep(1000);
        printf("A进程的X线程: %d\r\n",i);
    }
    //释放令牌
    ReleaseMutex(g_hMutex);
    return 0;
}

3. 互斥体与线程锁的区别

  1. 线程锁只能用于单个进程间的线程控制

  2. 互斥体可以设定等待超时,但线程锁不能

  3. 线程意外终结时,Mutex可以避免无限等待

  4. Mutex效率没有线程锁高

4. 互斥体防止多开

互斥体MSDN返回值:
如果函数成功.则返回互斥体的句柄.如果调用此函数.发现名字已经有了.表示这个函数在之前已经调用过了.所以则会返回 ERROR_ALREADY_EXISTS的宏. 这个宏的意思就是已经存在.

如果函数失败.则返回NULL. 返回的宏必须调用 GetlastError获取.

c

# include <Windows.h>
//创建临界区结构

int main(int argc, char *argv[])
{
    //初始化临界区全局原子变量
    HANDLE MutexHandle = CreateMutex(NULL, FALSE, TEXT("AAA"));  //创建互斥体. 信号量为0. 有信号的状态.wait可以等待
    DWORD ErrorCode = 0;
    ErrorCode = GetLastError();
    if (ERROR_ALREADY_EXISTS == ErrorCode)    //==时,说明已经不是第一次启动了
    {
        printf("对不起,程序已经启动一份了.这份即将关闭\r\n");
        CloseHandle(MutexHandle);

        system("pause");
    }
    if (NULL == MutexHandle)
    {
        return 0; //表示句柄获取失败
    }

    for (size_t i = 0; i < 10; i++)
    {
        Sleep(1000);
        printf("当前程序运行中. EIP 位置 等于 %d \r\n", i);
    }
    system("pause");
    return 0;
}

本文作者:Na1r

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!