37

I have some questions regarding read-write locks in POSIX Pthreads on a *nix system, say Linux for example.

I wish to know what is the default bias for read write lock i.e does it prefer reads over writes or vice versa ? Does it provide some api to change this default behaviour.

Does posix pthread provide some api so that we could change the pthread_rwlock_t to prevent writer starvation ? From what i have read(please correct me if i am wrong), the default implementation is biased towards reader threads and so writer threads can face starvation.

I have read the sample implementation of rw lock from the book Programming with Posix threads by David Butenhof.

I wish to know how posix pthreads handle starvation of writer threads ? Is there some api using which we could set the attributes of the read write lock that would prevent write starvation (i have never heard about that) ? Or does the user have to handle this problem ?

If you think that the answer is implementation-defined then please give me example of how it's done in Linux, because thats what i am looking for.

Please note that i just want solutions for a *nix system. Don't think that i am rude, but posting some windows-specific code is useless for me.

Thank you all for your help and patience :)

Reb.Cabin
  • 5,426
  • 3
  • 35
  • 64
ghayalcoder
  • 1,675
  • 2
  • 17
  • 24
  • Using a mutex instead of an rwlock will avoid this problem. If contention is low, it is also faster in some implementations (such as those that construct an rwlock from a mutex and a condition variable). – jilles May 15 '11 at 19:15

1 Answers1

54

This does indeed depend on the implementation - so since you have asked about Linux specifically, my comments are refer to the current NPTL implementation of pthreads, which is used in modern glibc.

There are two related, but separate, issues here. Firstly, there is this situation:

  • There are read locks currently held, and writers waiting. A new thread tries to take a read lock.

The default action here is to allow the reader to proceed - effectively "jumping the queue" over the writer. You can, however, override this. If you use the pthread_rwlockattr_setkind_np() function to set the PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP flag on the attr that you pass to pthread_rwlock_init(), then your rwlock will block the reader in the above situation.

The second situation is:

  • The last holder releases the lock, and there are both readers and writers waiting.

In this situation, NPTL will always wake up a writer in preference to a reader.

Taken together, the above means that if you use the PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP flag, your writers shouldn't be starved (of course, now a continuous stream of writers can starve the readers. C'est la vie). You can confirm all this by checking the sources (it's all very readable1) in pthread_rwlock_rdlock.c and pthread_rwlock_unlock.c.

Note that there is also a PTHREAD_RWLOCK_PREFER_WRITER_NP, but it appears not to have the right effect - quite possibly a bug (or possibly not - see comment by jilles below).


1. ...or at least it was, back when I wrote this answer in 2010. The latest versions of NPTL are considerably more complex and I haven't re-done the analysis.
caf
  • 233,326
  • 40
  • 323
  • 462
  • thanks a lot. This is what i was looking for. One more thing, is the function pthread_rwlockattr_setkind_np() a POSIX api or only linux specific ? I could not see it in the /usr/include/pthread.h header file on my linux system(may be its old). And what does "np" stands for ? Thanks a lot :) – ghayalcoder Feb 03 '10 at 08:10
  • 1
    It's listed as a UNIX98 extension here: http://nptl.bullopensource.org/Tests/Optimization-level-in-nptl.html but I believe that's an error, and it's actually a GNU extension (as are all the other functions ending in `_np`). Certainly in practice it's not available elsewhere. I presume `_np` is short for `NPTL`, which means "Native POSIX Threads Library". I'm not sure exactly which version of glibc introduced it, but glibc 2.7 on my box has it. Maybe ask on the glibc mailing list? – caf Feb 03 '10 at 22:03
  • 5
    Hmm, I think I presumed wrong, and `_np` might well actually just mean "non-portable". – caf Mar 02 '11 at 13:27
  • Why in the world anyone would make their RW-lock implementation favor readers over writers by default is beyond me... – R.. GitHub STOP HELPING ICE May 11 '11 at 23:14
  • 3
    @R.. I think the reason is that `PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP` causes deadlock when a thread locks for reading recursively and a writer arrived between the two lock operations, and this deadlock is considered "worse" than preferring readers over writers, probably because POSIX requires recursive read locks. If the deadlock is fixed, there seems little reason for different kinds of rwlock. For example, if there is a writer waiting, FreeBSD allows a reader to enter iff the thread already owns an rwlock in read mode (it does not track all owned rwlocks, just how many there are). – jilles May 15 '11 at 18:05
  • @jilles: Interesting. Where though does POSIX require true recursive behavior and not just "multiple-owner" behavior? All I can find is "If the Thread Execution Scheduling option is not supported, it is implementation-defined whether the calling thread acquires the lock when a writer does not hold the lock and there are writers blocked on the lock." which seems to imply that the deadlock in this case is valid... – R.. GitHub STOP HELPING ICE May 16 '11 at 00:24
  • 1
    @R.. The paragraph starting with "A thread may hold multiple concurrent read locks" permits applications recursive read locks. If they are permitted, it would be strange if they deadlocked in a fairly normal situation. On the other hand, recursive write locks may deadlock or fail. – jilles May 18 '11 at 18:49
  • I agree it would be a bit strange for them to deadlock, but I'm not sure it's required that they not deadlock. I wonder if it's possible to make a rwlock that both permits recursive read locking without deadlock, and prefers writers, with bounded memory usage. Naively, it seems impossible. – R.. GitHub STOP HELPING ICE May 18 '11 at 19:11