recursive mutexはいつ使う?

POSIX recursive mutexに関するDavid Butenhof氏*1の見解。2005年のニュースグループcomp.programming.threads投稿より部分引用。*2


  • 原則、recursive mutexを使ってはならない。POSIX recursive mutexは、レガシーコード保護用のグローバルMutexを避けるためのハック(hack)として導入された。
  • 正しく良い設計の並行処理ではrecursive mutexを必要としない。最初からそれに頼るのは怠慢であり邪悪な行為である。
  • 自身の設計範囲外にある他コードとの関係上、どうしてもrecursive mutexが必要になったら使用すればよい。

A correct and well understood design does not require recursive mutexes. While recursive mutexes may seem a convenience for debugging, in fact it's the opposite -- you're better off with a "strict" debugging mutex (like the POSIX error-check attribute) that checks, tracks, and enforces ownership restrictions a "normal" mutex may ignore in favor of runtime efficiency.

And so DCE threads has pthread_lock_global() and pthread_unlock_global(). But if that's all that's necessary, why does POSIX have recursive mutexes?

Because of a dare.

1) The biggest of all the big problems with recursive mutexes is that they encourage you to completely lose track of your locking scheme and scope. This is deadly. Evil. It's the "thread eater". You hold locks for the absolutely shortest possible time. Period. Always. If you're calling something with a lock held simply because you don't know it's held, or because you don't know whether the callee needs the mutex, then you're holding it too long. You're aiming a shotgun at your application and pulling the trigger. You presumably started using threads to get concurrency; but you've just PREVENTED concurrency.

2) Sometimes you need to unlock. Even if you're using recursive mutexes. But how do you know how to unlock? Threaded programming is built around predicates and shared data. When you hand a recursive mutex down from one routine to another, the callee cannot know the state of predicates in the caller. It has to assume there are some, because it cannot verify there aren't; and if the caller had known that there were no broken predicates, it should have allowed concurrency by unlocking.

Recursive mutexes are a hack. There's nothing wrong with using them, but they're a crutch. Got a broken leg or library? Fine, use the crutch. But at least be aware that you're using a crutch, and why; and once in a while check out the leg (or library) to be sure you still need the crutch. And if it's not healing up, go see a doctor, because that's just not OK. When you have no choice, there's no shame in using a crutch... but you can't run very well on a crutch, and you'll also be slowing down anyone who depends on you.


*1:同氏はPOSIX Threads仕様策定にも関わっている。書籍"Programming with POSIX Threads"の著者。

*2:本記事は https://twitter.com/yohhoy/status/655530353835180032 https://twitter.com/yohhoy/status/655532159373938688 をきっかけに調べた内容