I've been working on a small sand-boxed example to help me figure out how to use rwlocks. Everythin开发者_运维技巧g seems fairly straightforward, however I'm getting deadlocks in my example every once and a while and don't understand why it's happening.
I've put the code example on pastebin because it's more than a few lines of code: http://pastebin.org/359203
If you run the example. When it eventually deadlocks the last three print statements will be one of two cases:
one:
th4: request lock
th3: request lock
th4: locked
two:
th3: request lock
th4: request lock
th3: locked
Based on the output. To me it seems like there is an eventual deadlock from a second call to a locking function, whether it's to a read lock, or a write lock. But since one of the threads has the lock, and the same thread is what calls the second locking function, why is it deadlocking? Even more interesting, what is it in this small case that is causing the deadlock?
Note that I'm on Mac OS X, and that this is a seriously contrived example. It's sand-boxed from something else I'm working on and wanted to make sure I get this part right.
pthread_rwlock supports recursive read locking, but not recursive write locking. If you write lock the lock while you already hold it, you have entered the realm of undefined behavior. This is the case for your thfn3()
.
It's clearer if you call the threads the "reader" (thfn4) and the "writer" (thfn3). Case one is then:
- reader tries to lock
- writer tries to lock and blocks waiting for reader to release lock
- reader gets lock
- reader tries to lock again and blocks waiting for writer to acquire lock and release lock
In this case, the reader is likely unable to lock again because there is a writer waiting on the lock, and would-be writers block would-be readers.
Case two is:
- writer tries to lock
- reader tries to lock and blocks waiting for writer to finish
- writer gets lock
- writer tries to lock again and blocks
This case can likely only be explained by appeal to details of the rwlock implementation.
Your problem is that pthread_rwlock_wrlock(3)
is not reentrant. The documentation clearly states that the results of calling this method when the thread already holds the lock are undefined. Your code specifically calls the method twice without releasing the lock in between.
See the bug I reported with apple. This is the problem.
https://bugreport.apple.com/cgi-bin/WebObjects/RadarWeb.woa/7/wo/0blX77DJS8lBTTxVnTsNDM/5.83.28.0.13
Here's the open radar bug.
http://openradar.appspot.com/8588290
I posted a workaround for this question in Pthread RWLock on MAC Deadlocking but not on Linux?
It is platform independent, and the general method ought to allow for other tricks like upgrading from read to write, etc.
精彩评论