• 线程同步互斥之互斥量(Mutex)


      上一篇文章复习了下临界区(Critical Section),现在来复习下互斥量对象(Mutex Object)。
      其实互斥对象和临界区对象差不多,都是为了在多个线程访问公共数据块时,只允许一个线程访问此公共数据块。但是临界区是用户对象,互斥是内核对象;还有,在效率上来说,临界区效率高于互斥对象,下面来具体的看看。
      准备知识:
      1、内核对象互斥体(Mutex)的工作机理,WaitForSingleObject函数的用法,这些可以从MSDN获取详情;
      2、当两个或更多线程需要同时访问一个共享资源时,系统需要使用同步机制来确保一次只有一个线程使用该资源。Mutex 是同步基元,它只向一个线程授予对共享资源的独占访问权。如果一个线程获取了互斥体,则要获取该互斥体的第二个线程将被挂起,直到第一个线程释放该互斥体。
    下面是自己写的一个小Demo,具体代码如下:

    #include <iostream>
    #include <Windows.h>
    using namespace std;
    static HANDLE g_hMutex = INVALID_HANDLE_VALUE;
    static int g_Count = 100;
    DWORD WINAPI Thread1(LPVOID LPparameter);
    DWORD WINAPI Thread2(LPVOID LPparameter);
    
    int main()
    {
        HANDLE thread1 = INVALID_HANDLE_VALUE;
        HANDLE thread2 = INVALID_HANDLE_VALUE;
        g_hMutex = CreateMutex(NULL, false, TEXT("Mutex"));
        if(!g_hMutex)
        {
            return -1;
        }
    
        thread1 = CreateThread(NULL, 0, Thread1, NULL, 0, NULL);
        thread2 = CreateThread(NULL, 0, Thread2, NULL , 0, NULL);
        Sleep(5000);
        CloseHandle(thread1);
        CloseHandle(thread2);
        return 0;
    }
    
    
    DWORD WINAPI Thread1(LPVOID LPparameter)
    {
        while(1)
        {
            WaitForSingleObject(g_hMutex, INFINITE);
            if(g_Count>0)
            {
                //Sleep(20);
                cout<<"thread1:"<<g_Count--<<endl;
                ReleaseMutex(g_hMutex);
            }
            else
            {
                ReleaseMutex(g_hMutex);
                break;
            }
        }
    
        return 0;
    }
    
    DWORD WINAPI Thread2(LPVOID LPparameter)
    {
        WaitForSingleObject(g_hMutex, INFINITE);
        while(1)
        {
            if(g_Count>0)
            {
                //Sleep(20);
                cout<<"thread2:"<<g_Count--<<endl;
                ReleaseMutex(g_hMutex);
            }
            else
            {
                ReleaseMutex(g_hMutex);
                break;
            }
        }   
        return 0;
    }

    个人感觉使用互斥对象的大概分为这个几个步骤:
    1、调用CreateMutex函数创建互斥对象;
    2、在线程中调用WaitForSingleObject函数等待线程(这个解释可能不是很清楚,可以自己查询MSDN看那看,这个函数有很多用处)。
    3、在线程保护完相关的公用数据后调用ReleaseMutex函数释放互斥对象的资源。

    具体的使用的API的解释如下:
    HANDLE CreateMutex(
    LPSECURITY_ATTRIBUTES lpMutexAttributes, // 指向安全属性的指针
    BOOL bInitialOwner, // 初始化互斥对象的所有者
    LPCTSTR lpName // 指向互斥对象名的指针
    );
    功能:创建一个互斥对象
    参数:lpMutexAttributes,互斥的安全属性,一般为NULL,使用默认安全属性
    参数:bInitialOwner,初始化互斥对象的所有者
    参数:lpName,互斥对象的名称
    返回值:返回一个互斥对象的句柄。

    BOOL WIANPI ReleaseMutex(
    HANDLE hMutex
    );
    功能:释放一个互斥对象。
    参数:hMutex,需要释放互斥对象。
    返回值:TRUE为成功,FALSE为释放失败。

    DWORD WaitForSingleObject(
    HANDLE hHandle,
    DWORD dwMilliseconds
    );
    功能:等待指定对象那的状态(这个解释不一定正确,可以自己去查询MSDN)。
    参数:hHandle,指定的对象的句柄,如何互斥量句柄或事件对象的句柄等。
    参数:dwMilliseconds,定时时间间隔,单位为milliseconds(毫秒).如果指定一个非零值,函数处于等待状态直到hHandle标记的对象被触发,或者时间到了。如果dwMilliseconds为0,对象没有被触发信号,函数不会进入一个等待状态,它总是立即返回。如果dwMilliseconds为INFINITE,对象被触发信号后,函数才会返回。
    返回值:执行成功,返回值指示出引发函数返回的事件。

  • 相关阅读:
    ajax三级联动
    ajax基础
    pdo连接数据
    jquery选择器和基本语句
    会话
    封装连接类
    1218数据访问
    php登陆与注册
    数据库连接和乱码问题
    mysql 严格模式 Strict Mode说明(text 字段不能加默认或者 不能加null值得修改方法)
  • 原文地址:https://www.cnblogs.com/huiz/p/9610678.html
Copyright © 2020-2023  润新知