多个互斥锁上的Windows同步

时间:2012-06-09 17:42:11

标签: c++ winapi synchronization mutex waitformultipleobjects

我不清楚这个,有人能为我确认一下吗?

我有以下同步问题。我有以下对象:

A. Process 1, thread 1: Read & write access to the resource.
B. Process 1, thread 2: Read access to the resource.
C. Process 2, thread 3: Read access to the resource.

这是访问条件:

  1. 在B或C开启时必须阻止A.
  2. 只有当A打开时,
  3. B必须被阻止。
  4. 只有在A打开时才能阻止C.
  5. 所以我想为此使用2个命名的互斥锁:

    • hMutex2 =用于满足上述条件2.
    • hMutex3 =用于满足上述条件3.
    • hStopEvent =停止事件(如果应用程序正在关闭,则需要停止线程)。

    所以A:

    HANDLE hHandles[3] = {hMutex2, hMutex3, hStopEvent};
    DWORD dwRes = WaitForMultipleObjects(3, hHandles, FALSE, INFINITE);
    if(dwRes == WAIT_OBJECT_0 + 2)
    {
        //Quit now
        return;
    }
    else if(dwRes == WAIT_OBJECT_0 + 0 ||
        dwRes == WAIT_OBJECT_0 + 1)
    {
        //Do reading & writing here
        ...
    
        //Release ownership
        ReleaseMutex(hMutex2);
        ReleaseMutex(hMutex3);
    }
    else
    {
        //Error
    }
    

    对于B:

    DWORD dwRes = WaitForSingleObject(hMutex2, INFINITE);
    if(dwRes == WAIT_OBJECT_0)
    {
        //Do reading here
        ...
    
        //Release ownership
        ReleaseMutex(hMutex2);
    }
    else
    {
        //Error
    }
    

    对于C:

    DWORD dwRes = WaitForSingleObject(hMutex3, INFINITE);
    if(dwRes == WAIT_OBJECT_0)
    {
        //Do reading here
        ...
    
        //Release ownership
        ReleaseMutex(hMutex3);
    }
    else
    {
        //Error
    }
    

    有人可以证实这一点:

    • 在两个互斥锁上调用WaitForMultipleObjects时,它们是否都会发出信号(或被阻止)?
    • 我是否还需要释放两个互斥锁?

3 个答案:

答案 0 :(得分:1)

写入的WaitForMultipleObjects调用(第3个参数为FALSE)将在任何一个互斥锁发出信号时返回。这意味着编写者和其中一个读者都可以同时访问资源。一个读者可以访问该资源,而另一个读者释放其互斥锁。那时,作家将被释放。

因此,要使用这两种互斥体,您需要等待它们。但是,您不能将第三个参数设置为TRUE,因为这意味着它还需要发出信号以便发布该线程(显然不需要)。

一种可能性可能是检查释放了哪个互斥锁,然后让编写者在继续之前等待另一个。然后它需要在完成任务后释放它们。这种解决方案的一个问题是,它可能会匆忙开始变得复杂,如果添加更多需要互斥锁的进程,如果不小心,最终可能会出现死锁。使用读写器类型的锁可以简化处理过程。

编辑这不是问题答案的一部分,但取决于所涉及的流程以及访问资源的频率以及访问互联网时持有互斥锁的时长,通过使用一个互斥锁并将其视为关键部分,可以真正简化它...每个进程在需要访问资源时获取它。然而,它当然不允许两个读取器线程/进程具有并发访问,因此可能或可能不可接受。但从长远来看,验证要容易得多。

答案 1 :(得分:0)

事实上,我可以反驳它。 WaitForMultipleObjects参数设置为waitAll的{​​{1}}将在任何对象发出信号时返回。 Here's the documentation :)将其设置为FALSE,您将等待所有对象。

你的解决方案不能很好地扩展,但是:添加另一个阅读主题,你就会遇到第三个互斥锁......

然而,Writer/Readers problem已经多次解决过了;为什么不看看现有的实施?将节省大量的调试时间,特别是如果您还不熟悉Windows同步API。 (预告:posix线程有一个readwritelock,boost有一个TRUE。)

答案 2 :(得分:0)

您正在寻找的是读写器锁定。在你的算法中有一个严重的问题 - 进程A的饥饿:如果B和C继续工作并且使用它们的互斥锁,A可能无法进入。

相关问题