2014-02-14 57 views
3

我想使用Boost的upgrade_lock(使用this example,但我碰上一个饥饿的问题。其实我用从this post代码饥饿与upgrade_lock

,但我想一个跟上时代的讨论。我在WorkerKiller后运行400个线程。我遇到相同问题的anoneironaut,在mentionned帖子的作者。

我已经看到霍华德Hinnant(欣南特)的命题,但我真的不希望包括m矿石外部代码(此外,我无法让他编译到现在为止),并在6个月后发布的评论声明“Boost现在使用公平实现”(12年3月12日)。

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.". 

,并存入亚历山大捷列霍夫的算法是霍华德Hinnant(欣南特)会谈,所以我期望的1.55提升执行的行为像霍华德Hinnant(欣南特)的一答案,事实并非如此。它的行为与问题完全相同。

为什么我的WorkerKiller患有饥饿?

更新:将其用this code观察:

  • 的Debian 64,升压1.55(二者Debian版和一个从来源汇编),与两个铛++和g ++
  • Ubuntu的64位, Boost 1.54,同时有铿锵++(3.4-1ubuntu1)和g ++(4.8.1-10ubuntu9)
+0

你运行的是什么编译器和平台?我无法在VC11 x64版本上重现Boost 1.55的问题。 – ComicSansMS

+0

这很有趣。我复制了我的代码[在这里](https://gist.github.com/anonymous/bd3440d438da82061f22)。它在Debian(boost 1.55)和Ubuntu(boost 1.54)上使用clang ++和g ++进行了测试。 – JonesV

+0

现在明白了,我并没有意识到你正在使用'upgrade_lock'而不是普通的独占锁。 – ComicSansMS

回答

1

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

让我们首先弄清楚共享所有权和可升级所有权的概念。 对于SharedLockable,线程必须事先决定是要更改对象(要求独占所有权)还是仅从中读取(共享所有权)。如果拥有共享所有权的线程决定要更改该对象,它首先必须释放其对该对象的共享锁,然后构造一个新的独占锁。在这两个步骤之间,线程根本不在对象上锁定任何锁。试图从已经拥有共享锁的线程构造排它锁将会死锁,因为独占锁构造函数会阻塞,直到所有共享锁被释放。

UpgradeLockable克服了这个限制,允许将共享锁升级到独占锁而不释放它。也就是说,线程始终保持对互斥锁的主动锁定,同时禁止其他线程获得排他锁。除此之外,UpgradeLockable仍允许来自SharedLockable的所有操作,前者的概念是后者的超集。 question you linked to只关心SharedLockable概念。

无论是概念,通过升压规定,需要实施是公平的。然而,是Boost对SharedLockable的最小实现,确实为您的问题引用了公平性保证。请注意,这是附加保证这个概念实际需要的内容。

不幸的是,最小的实施升级所有权,该upgrade_mutex,不给这个附加出示担保。它仍然实施共享所有权概念作为可升级所有权的要求,但由于合规实施不需要公平性,所以它们不提供。

由于pointed out by Howard in the comments,Terekhov的算法可以进行微调,以适应可升级的锁,这只是Boost实现目前不支持的。

+0

好的,我明白了。但我真的不知道为什么UpgradeLockable可以防止获取独占锁的其他线程,而不是阻止他们获得一个共享锁...我可以使用独占互斥实现公平,[喜欢我在此代码做(HTTPS ://gist.github.com/anonymous/4f3f1bbcd7fe565b7876)。无论如何,我认为他们都保证公平,所以感谢您的发展;-)。 – JonesV

+0

@JonesV认为它是这样的:一个升级锁的行为像一个共享锁,与你只能有一次一个升级锁除外。所以一个活动的升级锁确实可以防止其他独占锁,但不会阻止其他共享锁(就像普通的共享锁一样)。公平的问题在于,当您尝试将升级锁变为独占锁时,此行为不会改变:即使您已经宣布您需要独占锁,其他共享锁仍会通过。 – ComicSansMS

+0

我明白这一点。我的意思是我不明白为什么它不能以公平的方式实施。我在之前的评论中链接的代码似乎比原来的更公平,至少=)。但也许正是因为'/'解锁()'指示... – JonesV