我试图了解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()一起使用是不好的做法?