线程同步互斥之互斥量(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,对象被触发信号后,函数才会返回。
返回值:执行成功,返回值指示出引发函数返回的事件。

猜你喜欢

转载自blog.csdn.net/u013421892/article/details/47836225