0

我不清楚这一点,有人可以帮我确认一下吗?

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

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. A 必须在 B 或 C 打开时被阻止。
  2. 只有在 A 开启时才能阻止 B。
  3. 只有在 A 开启时才能阻止 C。

所以我想为此使用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 时,它们是否都变为信号(或阻塞)?
  • 我还需要释放两个互斥锁吗?
4

3 回答 3

2

当任何一个互斥体发出信号时, WaitForMultipleObjects调用(第三个参数为 FALSE)将返回。这意味着作者和其中一位读者都可以获得对资源的同时访问。一个阅读器可能正在访问资源,而另一个阅读器释放其互斥体。届时,作家将被释放。

所以要像这样使用两个互斥锁,你需要等待它们。但是,您不能只将第三个参数设置为 TRUE,因为这意味着它还需要发出 hStopEvent 信号才能释放该线程(这显然是不希望的)。

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

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

于 2012-06-09T18:00:08.500 回答
0

事实上,我可以反驳它。 如果有任何对象发出信号 WaitForMultipleObjects,则waitAll参数设置为FALSE将返回。这是文档 :) 将其设置为,您将让它等待所有对象。TRUE

但是,您的解决方案不能很好地扩展:添加另一个阅读线程,并且您遇到了第三个互斥锁......

然而,Writer/Readers 问题之前已经解决了很多次;为什么不看看现有的实现呢?将为您节省大量调试时间,尤其是在您还不熟悉 windows 同步 API 的情况下。(预告片:posix 线程有一个读写锁,boost 有一个shared_mutex。)

于 2012-06-09T17:59:55.023 回答
0

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

于 2012-06-09T18:00:53.680 回答