David Barrett wrote:
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"-----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:
No. A write lock is always exclusive.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?
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.
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.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 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.)
But regardless, I get what APR does, I have a workaround, and all is rightI 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.
in the world.
-- Brane