如何等待互斥锁解锁?

3

这里有一个互斥锁数组。

  1. 检查互斥锁是否被锁定

2a. 如果没有锁定,就锁定它

2b. 如果已经锁定,就等待解锁并锁定它

另一个函数负责解锁。

问题在于,在等待部分出现了崩溃:

HANDLE mutexes[N];

void func(int i)
{
  // (*) wait until unlocked or create if unlocked
  while ((mutexes[i] = CreateMutex(NULL, TRUE/*same with FALSE*/, NULL)) != NULL);
  /*or WaitForSingleObject(mutexes[i], INFINITE)*/

  mutexes[i] = CreateMutex(NULL, TRUE, NULL);
}

在 (*) 点,我遇到了崩溃 - 访问冲突。当它尝试创建先前已经创建的mutexes[i]时,就会发生崩溃。我不能使用WaitForSingleObject,因为第一次mutexes[i]没有被创建,文档说WaitForSingleObject未定义。而且如果我使用这个函数,我会遇到同样的崩溃。

我只需要类似于这种简单伪代码的模拟

if (mutex_has_been_created[mutexes[i]])
  WaitUntilRelease()
CreateMutex();

我尝试将它包装在关键段中,但结果相同。我确信i在正确的范围内。 我不能使用Boost / pThreads等。
我知道我的问题非常简单,但我找不到解决方法。在我看过的所有示例中,在WaitForSingleObject之前创建了互斥体,但这对我不起作用。
谢谢。
4个回答

15
您需要整理代码逻辑:创建互斥锁和锁定/解锁是不同的操作,应该分别处理。坦率地说,“尝试创建已经创建了的互斥锁”的所有这些业务都没有多大意义。
简而言之:
  1. CreateMutex 初始化(“创建”)互斥锁。
  2. WaitForSingleObject 等待锁定互斥锁(或超时)。
  3. ReleaseMutex 解锁它。
  4. CloseHandle 销毁它。
您只需创建/销毁互斥锁一次,在其间隔内可以任意多次锁定/解锁它。
当您尝试锁定已被其他线程占用的互斥锁时,您的线程会自动阻塞,直到该互斥锁变为可用状态。

我以为CreateMutex的意思是锁定它。我没有找到“LockMutex”函数或类似的东西。 - fogbit
1
@fogbit:不,CreateMutex是用于初始化互斥量的。 WaitForSingleObject用于锁定它。请查看我的更新答案。 - NPE

4

如果你想等到互斥锁被解锁,然后再加锁它,那么你可以直接加锁。这就是当你这样做时会发生的事情。当你尝试加锁时,代码块会阻塞,直到互斥锁变为可用状态,然后加锁。


我不知道如何锁定它。我以为“创建互斥对象”意味着将其“锁定”。如果不是这样,那么我该如何在WinAPI中锁定它? - fogbit
3
这就是 WaitForSingleObject 的作用。 - R. Martinho Fernandes

1

使用 POSIX 线程,你可能会使用 条件变量;我不知道 WinAPI 是否提供类似的功能。


1
HANDLE mutexes[N]

void InitMutexes(int N)
{
    for (int i =0; i < N ; i++)
    {           
        mutexes[i] = CreateMutex( NULL, FALSE, NULL);
    }
}
void WaitForMutex(int n)
{
    WaitForSingleObject(mutexes[n], INFINITE);
}
void ReleaseMutex(int n)
{
    ReleaseMutex(mutexes[n]);
}
void CleanUpMutexes(int N)
{
    for (int i=0; i < N; i++)
    {
          ReleaseMutex(mutexes[i]); CloseHandle(mutexes[i]);
    }
}

希望这有所帮助。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接