2

我一直在寻找用于多处理同步的便携式强大解决方案。接触过这些东西的人都知道,好的解决方案是 boost::iterprocess 命名的同步对象。但是....当您的进程已named_mutex 锁定并且您的进程死亡(进程死亡时有许多正常情况,而不仅仅是错误或其他情况。)在这种情况下,named_mutex 将保持锁定状态。Ion Gaztanaga (www.boost.org/doc/libs/1_55_0/boost/interprocess/detail/robust_emulation.hpp)曾尝试在 boost 代码中制作robust_mutex

他很清楚如何解决放弃状态检查。游戏中的每个进程都有自己的锁定文件,当它处于活动状态时,它会锁定该文件。然后Ion的robust_mutex检查,如果锁定尝试失败,当前所有者进程锁定文件,并且可以确定当前互斥所有者是否活着。如果是死亡互斥锁,可以采取。文件锁的技巧是个好主意,因为如果进程死亡,操作系统会解锁文件锁,这似乎很容易移植。此解决方案包装基本 spin_mutex 并在内部字段中保存当前所有者进程 ID。我进行了密集测试,发现了两个大问题。

  1. 文件锁处理和实现方式会减慢互斥锁的速度,因为它更快,只需使用文件锁。

  2. 将有效的锁门变量和所有者进程 id 解耦会导致互斥锁可能被不同进程窃取的情况。

我的问题来了:我正在为这两个问题提出解决方案,我很想对此有一些专业的意见。

  1. 不要为每个现有进程使用单独的锁定文件,而是为所有最终进程 ID 使用一个文件(应该有足够的 4MB),并且每个进程锁定一个字节。该字节的位置由进程 ID 本身决定。(这不是我的想法,但我在Howard Chu 和他出色的 LMDB的代码中找到了它)

  2. 不要按原样包装 spin_mutex,而是重写它的代码,使其用作锁门当前所有者进程 id 而不是 0/1,因此锁定和解锁可以在一个原子 CAS 操作中发生。

我尝试实现它并在 Windows 上进行了测试。我使用原始的 boost 代码并在必要时调用 boost。这是代码。它取自我们的项目树,所以如果你想测试它,你可能必须调整一些包含。这是提议,所以请不要因为代码风格或其他原因责怪我。如果idea和mode好,我会继续完善。如果不是,我将使用其他东西,但我找不到其他东西。

还有 recursive_mutex 和 named_mutex 的版本。然后有一种修复建议,因为如果一个进程获得了所有权先前放弃的互斥锁,则很有可能必须进行某种完整性检查。

我想讨论最终的改进

先感谢您

拉迪斯拉夫。

4

0 回答 0