David Barrett wrote:

-----Original Message-----
From: Branko Čibej [mailto:[EMAIL PROTECTED]
Subject: Re: Can a thread write-lock a rwlock that it already has read-
locked?

David Barrett wrote:



I'm experimenting with the reader/writer locks and have a question:

        Can a thread write-lock a thread on which it already holds the read
lock?



No. A write lock is always exclusive.



Well yes, I agree. It's just that a write-lock seems to be a superset of
the read lock. In my mind, to have the write lock means I also must hold a
read lock, too (because I can both read and write). Thus from this
perspective, write-locking when I already have the read lock is akin to a
"write lock + nested read-lock". Nested read locks are allowed (at least I
think they are -- nested mutex locks are, at least), so I think this should
be too.


I think you're confused by the "read" and "write" in the names of the lock types. The "read" is a shared lock, which means that several threads/processes/whatever can hold it at the same time, while the "write" is an exclusive lock. Neither kind actually controls whether you can read from or write to the protected resource, but since the whole idea of locking is to prevent concurrent modifications to a resource, the terms "read lock" and "write lock" are used synonymously with "shared" and "exclusive"

Anyway, this is all moot.  I understand that APR disallows my desired
behavior (with a reasonable justification), and as a workaround I'm using
mutexes to create a read/write lock that works as I want.

But while I'm on the moot point, I might add I think my desired behavior is
*much* easier to work with.  Consider:

# get read lock
# result = long operation;
# if( result ) {
# get write lock
# do something
# release write lock
# }
# release read lock


Lock promotions are very hard to do correctly, and are usually not needed.

Without the ability to write lock while I hold the read lock, I'd need to
write-lock during the "long operation", even though it's not algorithmically
required. This blocks other threads for an unnecessarily long period.


But you can change your algorithm like this:

   done = false
   while not done:
     get shared lock
      result = long operation
      if result:
*        release shared lock
*        get exclusive lock
         if result is valid:
            do something
            done = true
         end if
         release exclusive lock
      end if
   end while

There is of course a race condition between releasing the shared lock and acquiring the exclusive lock, which is why you must check that the result is still valid after acquiring the exclusive lock


(If I had an atomic "upgrade to write lock" command I could do that too.
But without that, I can't safely give up the read lock and then grab the
write lock, because a thread might come in and invalidate the results of my
long operation.)


Excatly. That's why you have to check the validity of the result. If the price of having to recalculate the result is too high, or it happens too often, then its better to do everything under the exclusive lock.

But regardless, I get what APR does, I have a workaround, and all is right
in the world.


I wonder though iif your lock promotion scheme really works. Yes, it's possible to implement it, but I've never seen an implementation that, even when correct, is fair to all participating threads. For example, what happens if two threads try to promote their lock at the same time (that is, two are waiting on the promotion at the same time)? If you grant both requests, the one that comes in second will "do something" with a result that's no longer valid. If you only grant the first request, the second thread will have to recalculate its result again, and you end up with the same algorithm I outlined above, plus the overhead of a complex lock promotion implementation.

-- Brane



Reply via email to