bitsmcgee77 bitsmcgee77 - 27 days ago 16
Java Question

Using Java Queued Locks

I'm looking for a recommendation on how to make this code thread-safe with locks in Java. I know there are a lot of gotchas with locks; obscure problems, race-conditions, etc that can pop up. Here is the basic idea of what I'm trying to achieve, implemented rather naïvely:

public class MultipleThreadWriter {

boolean isUpgrading=false;
boolean isWriting=false;


public void writeData(String uniqueId) {

if (isUpgrading)
//block until isUpgrading is false

isWriting = true;
{
//do write stuff
}
isWriting = false;

}

public void upgradeSystem() {

if (isWriting)
//block until isWriting is false

isUpgrading = true;
{
//do updates
}
isUpgrading = false;

}

}


The basic idea is that multiple threads are allowed to write data simultaneously. It doesn't matter, since no two threads will ever be writing to data pertaining to the same uniqueId. However, the "system upgrade" manipulates data for all uniqueIds, so it must block (wait in line) until no data is being written before it can start, at which point it blocks all writes until it is finished. (It is definitely not a consumer/producer pattern going on here- upgrading occurs arbitrarily, i.e. has no relation to the data being written.)

Answer

This sounds like a good application for a readers-writer lock.

However, in this case your "readers" are the small update tasks that can all run concurrently, and your "writer" is the system upgrade task.

There's an implementation of this in the Java standard library:

java.util.concurrent.locks.ReentrantReadWriteLock

The lock has fair and non-fair modes. If you want the system upgrade to run as soon as possible after it's scheduled, then use the fair mode of the lock. If you want the upgrade to be applied during idle time (i.e., wait until there are no small updates going on), then you can use the non-fair mode instead.

Since this is a bit of an unorthodox application of the readers-writer lock (your readers are actually writing too!), make sure to comment this well in your code. You might even consider writing a wrapper around the ReentrantReadWriteLock class that provides localUpdateLock vs globalUpdateLock methods, which delegate to the readLock and writeLock, respectively.

Comments