user2953119
user2953119

Reputation:

ReadWriteLock. Understanding upgrading from readLock to writeLock

Consider this JDK standard interface:

public interface ReadWriteLock{
    public Lock readLock();
    public Lock writeLock();
}

B. Goetz in Java Concurrency in practice mentioned upgrading from readLock to writeLock is deadlock-prone.

If two readers simultaneously attempt to upgrade to a write lock, neither will realese the read lock.

The thing that's confused me is that it was two readers attempting to upgrade. But even one reader is enough, isn't? If a reader tries to upgrade it's not released the read lock yet. Trying to acquire the write lock with the read lock held is deadlocky.

So judging by that I think it's even theoretically nonsensical to provide the upgrade operation. Or maybe an implementation can take care of that?

Upvotes: 3

Views: 2270

Answers (2)

davmac
davmac

Reputation: 20631

It sounds like you are considering a "read lock" and a "write lock" to be two different locks which compose a read-write lock. That's not the correct way to think about it, even though the API seems to expose such a composition (by providing methods to obtain a reference to the "write lock" and to the "read lock").

(This is all confused a little by the overloading of the term "lock" - it is both a verb and a noun, that is, one can lock a lock).

Rather than thinking that ReadWriteLock's readLock method and writeLock method return actual locks, consider that what they actually do is return an abstract mechanism allowing acquisition of different types of lock (on the same, single, read-write lock mechanism).

A read-write lock (mechanism) is a single lock which can be locked in two ways: read-locked and write-locked. The read-write lock can be read-locked by one or more threads concurrently, or it can be write-locked. It can never be both read- and write- locked at the same time.

If a reader tries to upgrade it's not released the read lock yet. Trying to acquire the write lock with the read lock held is deadlocky.

A write lock is stronger than a read lock; it is like a read lock with an additional property (that no other thread may also hold the lock). Upgrading from a read-lock to a write-lock is not about acquiring one lock when another is already held; rather, it's about changing the type of lock which is already held on a single lock.

So, there is no conceptual problem with a single thread upgrading its read lock to a write lock; it just needs to wait until all other holders of the read lock relinquish it before the upgrade can occur. There is no possibility of deadlock in this case.

For instance, suppose there are three threads - A, B, and C, all which have read-locked the lock. Thread A tries to upgrade to a write-lock. This means it must wait for B and C to relinquish their read lock. This eventually happens, and at that point thread A acquires a write lock (and, eventually, thread A will then relinquish this lock).

On the other hand, consider if both A and B try to upgrade to a write lock. This means they are both waiting for the other one to relinquish the read lock, which won't happen; for thread A to relinquish the read lock, it would first need to acquire the write lock, which won't happen until thread B relinquishes the read lock, which it won't do until it acquires the write lock, which won't happen until thread A relinquishes the read lock ... and so on. There is a deadlock.

The Java API doesn't allow upgrading from a read-lock to a write-lock, since disallowing it prevents the deadlock scenario. It would be possible (if a little tricky) to write a program that could safely upgrade the lock type, but the Java API doesn't allow it regardless.

Upvotes: 9

Alexander Terp
Alexander Terp

Reputation: 425

The concept you're forgetting about is reentrancy, explained in section 2.3.2 of the book.

... if a thread tries to acquire a lock that it already holds, the request succeeds. Reentrancy means that locks are acquired on a per-thread rather than per-invocation basis.

Therefore, the single reader (i.e. single thread) would (in theory) be able to successfully acquire the write lock while also holding the read lock. Hence the need for two threads to demonstrate the deadlock issue with write upgrading.

Upvotes: 0

Related Questions