Multithreading 带升级锁的饥饿

Multithreading 带升级锁的饥饿,multithreading,boost,mutex,Multithreading,Boost,Mutex,我试图使用Boost的升级锁(使用,但我遇到了饥饿问题) 我实际上是在使用来自的代码,但我想要一个最新的讨论。我在WorkerKiller之后运行了400个线程。我遇到了与上述文章作者anoneironaut完全相同的问题 我已经看到了Howard Hinnant的建议,但我真的不想包含更多的外部代码(而且我现在无法让他编译),6个月后发布的一条评论指出,“Boost现在使用的是一个公平的实现”(12月3日) 缔约国指出: Note the the lack of reader-writer p

我试图使用Boost的升级锁(使用,但我遇到了饥饿问题)

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

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

缔约国指出:

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.". 
亚历山大·特列霍夫(Alexander Terekhov)的算法是霍华德·希南特(Howard Hinnant)所说的算法,因此我希望1.55 boost实现的性能与霍华德·希南特(Howard Hinnant)的答案类似,但事实并非如此。它的性能与问题中的完全相同

为什么我的工人杀手会挨饿?

更新:在以下时间观察到:

  • Debian x64,Boost 1.55(既有Debian版本,也有从源代码编译的版本),带有clang++和g++
  • Ubuntu x64,Boost 1.54,同时支持clang++(3.4-1ubuntu1)和g++(4.8.1-10ubuntu9)

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

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

      通过允许在不释放的情况下将共享锁升级为独占锁,克服了此限制。也就是说,线程始终保持互斥锁上的活动锁,同时禁止其他线程获取独占锁。此外,UpgradeLockable仍然允许来自SharedLockable的所有操作,前concept是后者的超集。只与SharedLockable概念有关

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

      不幸的是,可升级所有权的最小实现,即,并没有提供这一额外的保证。它仍然将共享所有权概念作为可升级所有权的一个要求来实现,但由于一致性实现不需要公平性,所以它们没有提供


      由于Terekhov的算法也可以简单地调整以使用可升级的锁,只是Boost实现目前不支持这一点。

      您运行的是什么编译器和平台?我无法在VC11 x64版本上重现Boost 1.55的问题。这很有趣。我复制了我的代码。它在Debian上进行了测试(boost 1.55)和Ubuntu(boost 1.54),使用了clang++和g++。现在我明白了,我没有意识到你使用的是
      upgrade\u lock
      而不是普通的排他锁。好的,我明白了。但我真的不明白为什么UpgradeLockable可以阻止其他线程获得排他锁,而不是阻止它们获得共享锁……我可以使用排他互斥来实现公平的锁定ness,。无论如何,我认为它们都保证了公平性,因此感谢您的开发;-)。@JonesV这样想:升级锁的行为类似于共享锁,但一次只能有一个升级锁。因此,主动升级锁确实阻止了其他独占锁,但不能阻止其他共享锁(就像普通共享锁一样)。公平性方面的问题是,当您尝试将升级锁转换为独占锁时,这种行为不会改变:其他共享锁仍然可以通过,即使您已经宣布需要独占锁。我理解这一点。我的意思是我不明白为什么它不能以公平的方式实施。我在之前的评论中链接的代码对我来说似乎比原来的代码更公平,至少=)。但是,由于额外的
      lock()
      /
      unlock()
      指令,它可能会更昂贵……Terekhov可以简单地调整以使用可升级的互斥锁: