multithreading - upgrade_lock 导致饥饿

标签 multithreading boost mutex

我正在尝试使用 Boost 的 upgrade_lock (使用 this example ,但我遇到了饥饿问题。

我实际上使用的是来自 this post 的代码,但我想要一个最新的讨论。我在 WorkerKiller 之后运行了 400 个线程。我遇到了与 anoneironaut 完全相同的问题,anoneironaut 是上述帖子的作者。

我已经看到了 Howard Hinnant 的提议,但我真的不想包含更多的外部代码(而且我现在无法编译他的代码)并且 6 个月后发布的评论指出“Boost 现在使用了一个公平的实现” (12 年 12 月 3 日)。

Boost 1.55 documentation指出:

Note the the lack of reader-writer priority policies in shared_mutex. This is 
due to an algorithm credited to Alexander Terekhov which lets the OS decide 
which thread is the next to get the lock without caring whether a unique lock or 
shared lock is being sought. This results in a complete lack of reader or writer
starvation. It is simply fair.". 

该算法归功于亚历山大·捷列霍夫 霍华德·欣南特 谈论,所以我希望 1.55 boost 实现的行为类似于 Howard Hinnant 的回答,但事实并非如此。它的行为与问题中的完全一样。

为什么我的 WorkerKiller 会饿死?

更新:观察到 this code在:
  • Debian x64,Boost 1.55(Debian 版本和从源代码编译的版本),带有 clang++ 和 g++
  • Ubuntu x64,Boost 1.54,带有 clang++ (3.4-1ubuntu1) 和 g++ (4.8.1-10ubuntu9)
  • 最佳答案

    这是一个微妙的。区别涉及共享和可升级所有权的概念,以及它们在 Boost 中的实现。

    我们先来梳理一下共享所有权和可升级所有权的概念。
    对于 SharedLockable ,线程必须事先决定它是要更改对象(需要独占所有权)还是只读取它(共享所有权就足够了)。如果具有共享所有权的线程决定要更改对象,则它首先必须释放对对象的共享锁,然后构造一个新的排它锁。在这两个步骤之间,线程根本不持有对象上的锁。尝试从已经持有共享锁的线程构造排他锁将死锁,因为排他锁构造函数将阻塞,直到所有共享锁都被释放。

    UpgradeLockable通过允许在不释放共享锁的情况下将共享锁升级为排他锁来克服此限制。即线程始终保持对互斥锁的事件锁,禁止其他线程在此期间获得排他锁。除此之外,UpgradeLockable 仍然允许所有来自 SharedLockable 的操作,前者概念是后者的超集。 question you linked to只关心 SharedLockable 概念。

    正如 Boost 所指定的,这两个概念都不需要实现是公平的。然而, shared_mutex ,这是 Boost 对 SharedLockable 的最小实现,确实提供了您问题中引用的公平保证。请注意,这是对概念实际需要的额外保证。

    不幸的是,可升级所有权的最小实现, upgrade_mutex , 不提供此额外保证。它仍然实现共享所有权概念作为可升级所有权的要求,但由于符合要求的实现不需要公平,因此他们没有提供它。

    pointed out by Howard in the comments , Terekhov 的算法也可以简单地调整以使用可升级的锁,只是 Boost 实现目前不支持这一点。

    关于multithreading - upgrade_lock 导致饥饿,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21773618/

    相关文章:

    c# - 我是否需要使用 try catch 或检查 ThreadPool.QueueUserWorkItem 的返回值

    java - 同步多个计时器以提高/降低速度

    python - 为什么我会丢失 SWIG、C++、python 的异常

    c++ - 如何使用 boost::asio::read_some 实现超时?

    c++ - 使用 std::mutex 时遇到问题

    c++ - 从线程执行的函数返回结构数组

    c++ - C++多线程设置中服务器重新初始化的良好设计

    c++ - 如何确定 boost::variant 变量是否为空?

    c++ - 单例的每个核心设计的 IO 服务

    c++ - protected 成员变量的错误共享?