views:

730

answers:

2

I'm using read/write locks on Linux and I've found that trying to upgrade a read locked object to a write lock deadlocks.

i.e.

// acquire the read lock in thread 1.
pthread_rwlock_rdlock( &lock );

// make a decision to upgrade the lock in threads 1.
pthread_rwlock_wrlock( &lock ); // this deadlocks as already hold read lock.

I've read the man page and it's quite specific.

The calling thread may deadlock if at the time the call is made it holds the read-write lock (whether a read or write lock).

What is the best way to upgrade a read lock to a write lock in these circumstances.. I don't want to introduce a race on the variable I'm protecting.

Presumably I can create another mutex to encompass the releasing of the read lock and the acquiring of the write lock but then I don't really see the use of read/write locks. I might as well simply use a normal mutex.

Thx

A: 

Easiest and safest would be to take the write-lock from the moment you could want to change your data instead of from the moment you're sure you will change it. I know that this will make access to your data a bit more serialized.

I was a bit surprised when reading this question, because I never even considered first taken a read-lock and then upgrading to a write-lock. Well, different situation could need different approaches.

stefaanv
It seems a bit over the top to acquire a write lock when you may not need it. This would serialise, as you pointed out. Whereas acquiring a read lock won't block. At the point you know you need to change something, you can upgrade to a write lock. It's just the actual act of doing so, under posix, introduces a race, which is a shame.
ScaryAardvark
It is a shame, but in most cases I know of, it is more a theoretical difference.
stefaanv
+1  A: 

What else than a dead lock do you want in the following scenario?

  • thread 1 acquire read lock
  • thread 2 acquire read lock
  • thread 1 ask to upgrade lock to write
  • thread 2 ask to upgrade lock to write

So I'd just release the read lock, acquire the write lock and check again if I've to make the update or not.

AProgrammer
Why would one of the thread get the write lock if the other is holding a read lock? And if both finally can get the write lock, the second one would have the problem that all checks that have been made have to be redone, as the protected resource may have been changed in significant way. Releasing and reacquiring thus provides the same behavior.
AProgrammer
@AProgrammer. I was hoping to avoid the second check on the object being locked. I know that IBM's implementation of read/write locks allows a calling thread to upgrade it's lock if it's the only thread holding a write lock. http://publib.boulder.ibm.com/infocenter/iseries/v5r4/index.jsp?topic=/apis/users_93.htm
ScaryAardvark
@nos. Yes, this would deadlock. T1 when asking to upgrade would be blocked from doing so as T2 has a read lock. T2 would then block when upgrading to write lock as T1 holds a read lock.
ScaryAardvark
@AProgrammer: in answer to your question "what do you expect", the answer is that if r/w locks are upgradeable then something like: thread 1's attempt to upgrade blocks, then thread 2's attempt fails. Thread 2 responds to this by releasing the reader lock and trying to re-acquire it and start all over again. Once it releases, Thread 1 can gain the writer lock, completes its transaction, and drops the lock. Anyone trying to get the reader lock while Thread1 was waiting on the writer lock, blocks until Thread1 releases both. Optimistic locking, sort of.
Steve Jessop