In Java's implementation locking, there is no way to atomically upgrade a lock from a read lock to write lock. For example, the following code snippet fails
ReentrantReadWriteLock lock = new ...
lock.readLock().lock();
boolean mustWrite = false;
// do somestuff and determine you must instead write! :-O
if(mustWrite) {
lock.writeLock().lock();
writeSomeStuff();
lock.writeLock().unlock();
}
lock.readLock.unlock();
The write lock acquisition has to wait for all read locks are done so it knows it's not overwriting data that readers might potentially be reading. That's bad. So the work around is to do something like this:
if(mustWrite) {
lock.readLock().unlock(); // let go of read before writing
lock.writeLock().lock();
writeSomeStuff();
lock.writeLock().unlock();
lock.readLock().lock(); // get back to reading
}
But this isn't ideal - someone might go and get do something in between when you unlock the read and pick up the write. Now it's probably a good idea to double check those conditions anyway, but still - it's ugly.
Now typically, when you acquire a lock you want to force your code to wait for it to actually acquire before you go doing what you're doing. You wouldn't want to just trust your locking mechanism that it will have given you your lock before you start messing with the data.
But why does it force you to halt execution from when you've signaled that you want the lock to when you're actually read to wait? For example, why couldn't it allow something like this:
lock.writeLock().notifyIntentToLock(); // puts you in line to get the write lock
// everyone else will block until you both
// acquire and release the lock
lock.readLock().unlock(); // proceed with the unlock so you don't deadlock
lock.writeLock().makeGoodOnIntentToLock(); // actually acquire that lock
So in a sense, the current lock functionality could be theorized as them both being done at the same time, like
public void lock() {
this.notifyIntentToLock();
this.makeGoodOnIntentToLock();
}
What design decisions would make them not allow some kind of delayed intent to lock? Is there a serious problem with a lock design like that that I'm simply not seeing?