apr-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Branko ─îibej <br...@xbc.nu>
Subject Re: Can a thread write-lock a rwlock that it already has read-locked?
Date Sun, 17 Oct 2004 17:01:38 GMT
David Barrett wrote:

>>-----Original Message-----
>>From: Branko ─îibej [mailto:brane@xbc.nu]
>>Subject: Re: Can a thread write-lock a rwlock that it already has read-
>>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
>>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

View raw message