【问题标题】:Locking and synchronization using Mutex使用 Mutex 进行锁定和同步
【发布时间】:2012-03-30 17:18:12
【问题描述】:

我正在创建一个程序,它将在多个进程和多个线程中运行相同的函数,所以我创建了一个函数来实现锁定和同步

HANDLE WaitOnMutex(char* mt)
{
    HANDLE ghMutex=NULL; 
    DWORD lastError=-1;
    do
    {
        ghMutex = CreateMutex(NULL,TRUE,mt);
        lastError=  GetLastError();
        if(lastError!=ERROR_SUCCESS)
        {
            CloseHandle(ghMutex);
            Sleep(2000);
        }
    }
    while(lastError!=ERROR_SUCCESS);
    return ghMutex;
}

我像下面这样使用它

    HANDLE mtx=WaitOnMutex("Global\\DBG_MY_APP");
    //Do the work that needs sync
    CloseHandle(mtx)

这是锁定此功能的正确方法吗?还是我需要使用不同的方法..

注意:我使用“全局”是因为我的应用程序的某些部分是 winService,我需要在会话隔离进程之间锁定

代码在测试环境中运行,但我不确定我的做法是否正确

【问题讨论】:

  • 你用错了方法。有关详细信息,请参阅此文档。 mutex msdn
  • @rbelli 可以请告诉我我的方式到底出了什么问题?
  • 如果我完全理解你在做什么,你只是在创建或打开互斥锁。你没有得到互斥锁。为此,正如我在示例中看到的,您需要调用函数 WaitForSingleObjects 来检查并获取互斥锁,然后调用函数 ReleaseMutex 来释放它。

标签: c multithreading winapi mutex


【解决方案1】:

您编写的代码是繁忙的等待,在大多数情况下都不太理想。不仅如此,您还把它封装在重量级的互斥体创建和释放调用中。

要使用命名互斥锁进行跨进程同步,每个进程应该只调用一次CreateMutex。然后,您保留互斥锁句柄,并使用WaitForSingleObject 等待它并使用ReleaseMutex 释放锁。然后,您可以在下次需要访问受保护的资源时使用 WaitForSingleObject 再次锁定它,依此类推。

当您的进程“永远”使用互斥锁完成时(例如,因为进程正在退出),然后您调用 CloseHandle

【讨论】:

  • 很好,但首先我不认为它很忙等待“睡眠(2000);”但我猜你对重量级互斥锁的创建是正确的。现在我的问题是函数 CreateMutex 可中断?如果是这样,那么我所有的工作都是错误的,如果不是,那么我的工作表现不佳..
  • 诚然,2秒的等待并不“忙”,但它仍然是一个轮询循环,它需要调度器唤醒线程只是为了检查它是否可以获取互斥体,然后返回睡觉。
  • CreateMutex 不能因为调度问题而“失败”,除非创建互斥锁的其他线程/进程更改了访问权限,因此您的线程/进程没有必要的权限。如果这没有发生,那么要么您的线程创建互斥体,然后您获得锁(因为您将“初始所有者”标志指定为真),或者另一个线程创建互斥体并且您获得句柄和ERROR_ALREADY_EXISTS错误代码,但不是锁。
【解决方案2】:

对于“工作”的足够宽松的定义,我想这会起作用。但这不是我的工作方式。

我想我会做更多这样的事情:

一次性初始化代码中的某处:

HANDLE mutex = CreateMutex(name); // yes, there are more parameters here.

然后写入日志:

WaitForSingleObject(mutex, INFINITE);

// write to log

ReleaseMutex(handle);

然后在一次性关闭代码期间:

CloseHandle(mutex);

如果您使用 C++ 而不是 C,您通常希望通过 RAII 来处理此问题,因此您需要创建一个日志对象,在其 ctor 中调用 CreateMutex,并在其中调用 CloseHandle dtor。然后你会有一个写函子,它在其ctor中执行WaitForSingleObject,在其operator()中写入日志,并在其dtor中执行ReleaseMutex。这样可以使您的大部分代码相对简单,并且只需很少或无需额外工作即可维护异常安全。

【讨论】:

  • 哎呀——看起来 Anthony 打败了我。
  • 我的新问题:函数 CreateMutex 是可中断的吗?如果是这样,那么我所有的工作都是错误的,如果不是,那么我的工作表现不佳..
  • 我想这有点取决于你所说的可中断是什么意思,但对你的代码来说,它就像是原子的。
  • 我所说的可中断是指CPU在执行时可以被中断,如果是这样,另一个进程可能会在另一个进程执行时进入createMutex,这将导致非锁定情况
  • @CnativeFreak:从这个角度来看,是的,它是原子的——虽然多个进程可以同时持有同一个互斥锁的句柄,但在任何给定时间只有一个进程拥有该互斥锁。
猜你喜欢
  • 2021-09-29
  • 2020-06-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-12
  • 2020-12-07
相关资源
最近更新 更多