如何在pthreads中的读写锁中防止编写器饥饿

gha*_*der 29 linux multithreading pthreads

我有一些关于*nix系统上POSIX Pthreads的读写锁的问题,例如Linux.

我想知道读写锁的默认偏差是什么,即它是否更喜欢读写,反之亦然?它是否提供一些api来更改此默认行为.

posix pthread是否提供了一些api,以便我们可以更改pthread_rwlock_t以防止作者饥饿?从我所读到的(如果我错了请纠正我),默认实现偏向于读者线程,因此作者线程可能面临饥饿.

我已经从David Butenhof的Programming with Posix threads一书中读到了rw锁的示例实现.

我想知道posix pthreads如何处理编写器线程的饥饿?是否有一些api使用,我们可以设置读写锁的属性,以防止写饥饿(我从来没有听说过)?或者用户是否必须处理此问题?

如果您认为答案是实现定义的,那么请举例说明它是如何在Linux中完成的,因为这就是我要找的东西.

请注意,我只想要一个*nix系统的解决方案.不要以为我很粗鲁,但发布一些特定于Windows的代码对我来说毫无用处.

谢谢大家的帮助和耐心:)

caf*_*caf 44

这确实取决于实现 - 所以既然你已经专门询问了Linux,我的评论是指现代的glibc中使用的pthreads的NPTL实现.

这里有两个相关但又分开的问题.首先,有这种情况:

  • 目前有读锁,写作等待.新线程尝试进行读锁定.

这里的默认操作是允许读者继续 - 有效地"跳过队列"在作者身上.但是,您可以覆盖它.如果您使用该pthread_rwlockattr_setkind_np()函数设置传递给的PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP标志,那么您的rwlock将在上述情况下阻止阅读器.attrpthread_rwlock_init()

第二种情况是:

  • 最后一个持有者释放锁,并且有读者和作者等待.

在这种情况下,NPTL总会唤醒作家而不是读者.

综上所述,上述意味着如果你使用PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP旗帜,你的作家就不应该被挨饿(当然,现在连续不断的作家可能会使读者们挨饿 .C'est la vie).您可以通过检查pthread_rwlock_rdlock.cpthread_rwlock_unlock.c中的源(它们都是非常易读的1)来确认所有这些.

请注意,还有一个PTHREAD_RWLOCK_PREFER_WRITER_NP,但似乎没有正确的效果 - 很可能是一个错误(或可能不是 - 请参阅下面的jilles评论).


1. ...或者至少是在2010年我写这个答案的时候.最新版本的NPTL要复杂得多,我还没有重新进行分析.

  • 嗯,我认为我认为是错的,而`_np`实际上可能只是意味着"非便携式". (4认同)
  • @R ..我认为原因是`PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP`在线程锁定以递归读取并且编写器在两个锁定操作之间到达时导致死锁,并且这种死锁被认为"比读者更喜欢读者",可能是因为POSIX需要递归读锁.如果死锁是固定的,那么似乎没有什么理由可以使用不同类型的rwlock.例如,如果有一个编写器在等待,FreeBSD允许读者输入iff线程已经在读取模式下拥有一个rwlock(它不跟踪所有拥有的rwlock,只跟踪有多少). (3认同)