您的位置:首页 > 其它

Windows 平台下的同步机制 (2)– 互斥体(Mutex)

2011-01-10 14:15 465 查看
windows api中提供了一个互斥体,功能上要比临界区强大。Mutex是互斥体的意思,当一个线程持有一个Mutex时,其它线程申请持有同一个Mutex会被阻塞,因此可以通过Mutex来保证对某一资源的互斥访问(即同一时间最多只有一个线程访问)。
调用CreateMutex可以创建或打开一个Mutex对象,其原型如下
HANDLE CreateMutex(
  LPSECURITY_ATTRIBUTES lpMutexAttributes,
  BOOL bInitialOwner,
  LPCTSTR lpName
);
其中参数lpMutexAttributes用来设定Mutex对象的安全描述符和是否允许子进程继承句柄。bInitialOwner表明是否将Mutex的持有者设置为调用线程。lpName参数设置Mutex的名字,该名字区分大小写并不能包含"",最大长度为MAX_PATH,可设置为NULL表明该Mutex为匿名对象。
如果调用成功,则返回Mutex的句柄,否则返回NULL,如果lpName不为NULL且调用前同名的Mutex已被创建,则返回同名Mutex的句柄,此时调用GetLastError将返回ERROR_ALREADY_EXISTS,参数bInitialOwner将被忽略。
还可以调用OpenMutex打开创建的非匿名Mutex,原型如下
HANDLE OpenMutex(
  DWORD dwDesiredAccess,
  BOOL bInheritHandle,
  LPCTSTR lpName
);
在成功创建或打开Mutex后,可以使用wait functions来等待并获取Mutex的持有权。
下面的例子用来通过Mutex对象控制某一应用程序只运行一次
    int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
    {
        HANDLE hMutex = CreateMutex(NULL, FALSE, "Mutex_Only_One_Instance_Allowed");
        if (NULL == hMutex)
        {
            Error("Create mutex error.");
            return -1;
        }
        DWORD dw = WaitForSingleObject(hMutex, 0);
        if (WAIT_FAILED == dw)
        {
            Error("Wait for mutex error.");
            CloseHandle(hMutex); // 释放句柄,当指向同一系统对象的所有句柄释放后,该对象将被删除。
            return -1;
        }
        else if (WAIT_TIMEOUT == dw)
        {
            // 另外一个实例正在运行
            CloseHandle(hMutex);
            return 1;
        }
        // 没有其它实例在运行,本实例将继续运行
        // 在此实现必要的功能性代码,如创建窗口,进入消息循环
        // ……………
        ReleaseMutex(hMutex); // 释放hMutex的持有权,注意这并不等同于删除Mutex对象
        CloseHandle(hMutex);
        return 0;
    }
其中WaitForSingleObject是等待特定对象发出信号(signaled),而Mutex对象在没有任何线程持有时会发出信号。
与临界区(critical section)有什么区别,为什么强大?它们有以下几点不一致:
1.critical section是局部对象,而mutex是核心对象。因此像waitforsingleobject是不可以等待临界区的。
2.critical section是快速高效的,而mutex同其相比要慢很多
3.critical section使用范围是单一进程中的各个线程,而mutex由于可以有一个名字,因此它是可以应用于不同的进程,当然也可以应用于同一个进程中的不同线程。
4.critical section 无法检测到是否被某一个线程释放,而mutex在某一个线程结束之后会产生一个abandoned的信息。同时mutex只能被拥有它的线程释放。下面举两个应用mutex的例子,一个是程序只能运行一个实例,也就是说同一个程序如果已经运行了,就不能再运行了;另一个是关于非常经典的哲学家吃饭问题的例子。
互斥体通常用于多进程之间的同步问题
程序运行单个实例:
#include "stdafx.h"
#include
#include
#include
using namespace std;
//当输入s或者c时候结束程序
void PrintInfo(HANDLE& h, char t)
{
    char c;
    while (1)
    {
        cin >> c;
        if (c == t)
        {
            ReleaseMutex(h);
            CloseHandle(h);
            break;
        }
        Sleep(100);
    }
}
int main(int argc, char* argv[])
{
    //创建mutex,当已经程序发现已经有这个mutex时候,就相当于openmutex
    HANDLE hHandle = CreateMutex(NULL, FALSE, "mutex_test");
    if (GetLastError() == ERROR_ALREADY_EXISTS)
    {
        cout << "you had run this program!" << endl;
        cout << "input c to close this window" << endl;
        PrintInfo(hHandle, ‘c’);
        return 1;
    }
    cout << "program run!" << endl;
    cout << "input s to exit program" <
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: