OpenMutex / CreateMutex竞争条件

时间:2018-10-08 18:57:04

标签: windows multithreading winapi

我试图了解OpenMutex MSDN文章警告我的这种竞争状况。从MSDN:

  

如果您的多线程应用程序必须重复创建,打开并   关闭一个命名的互斥对象,可能会发生竞争状况。在这   在这种情况下,最好使用CreateMutex而不是OpenMutex,   因为CreateMutex将打开一个互斥锁(如果存在)并创建一个互斥锁(如果存在)   没有。

相同的警告包含在Windows Internals 6th Edition第1部分中:

  

Windows还支持Ex(扩展)版本的   新增其他API的API(CreateEventEx,CreateMutexEx,CreateSemaphoreEx)   用于指定访问掩码的参数。这使得   适当使用酌情访问控制列表的应用程序   (DACL)保护其对象而不破坏其使用能力   创建对象API以打开它们的句柄。你可能是   想知道为什么客户端应用程序不会简单地使用OpenEvent,   确实支持所需的访问参数。使用打开的对象   在处理故障时,API会导致固有的竞争状况   在公开通话中-也就是说,当客户端应用程序尝试   在创建事件之前先打开它。在大多数应用中   在这种情况下,打开API失败后将创建API   案件。不幸的是,没有保证的方法来进行这种创建   原子操作-换句话说,仅发生一次。的确,   多个线程和/或进程执行了   同时创建API,并且所有尝试都在   同时。这种竞争条件和额外的复杂性   尝试处理它使使用开放对象API不合适   解决问题的方法,这就是为什么应使用Ex API的原因   代替。

假定多个线程试图同时调用OpenMutex(),结果将是失败的。然后这些线程将调用CreateMutex(),因此第一个线程将创建请求的互斥锁,其他线程将打开它。如果多个线程尝试调用CreateMutex()而没有使用OpenMutex,则情况相同。但是,如果CreateMutex()不是线程安全的,并且存在争用条件,那么它也将处于未使用OpenMutex()的情况。

有人可以告诉我什么情况会导致比赛状态吗?

更新1:

  

在大多数此类应用程序中,打开的API后面都带有一个   在失败的情况下创建API。不幸的是,没有保证   使此创建操作原子化的方法,换句话说,仅发生   一旦。实际上,可能有多个线程和/或   进程已同时执行创建API并进行所有尝试   同时创建事件。

为什么这是一个糟糕的情况?在所有线程在OpenMutex()上失败之后,它们将同时调用CreateMutex()。调用CreateMutex()时,一个线程将创建互斥锁,其他线程将打开该互斥锁。

所以我不明白为什么将OpenMutex()与后续的CreateMutex()一起使用是一个坏主意吗?

更新2:

我编写了一个可以在多个实例中运行的测试应用程序。循环中的每个实例首先尝试调用OpenMutex(),然后在发生错误的情况下调用CreateMutex()。在这两种情况下,应用程序都会编写互斥量打开/创建的结果,调用CloseHandle(),然后转到下一个迭代。我尝试过通过不同的时间(通过添加睡眠)来尝试不同数量的实例,但是调用CreateMutex()或任何意外行为时没有任何错误。

因此,问题仍然存在,为什么将OpenMutex()与后续的CreateMutex()一起使用是不好的做法?

0 个答案:

没有答案