简体   繁体   中英

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, ie has no relation to the data being written.)

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 (ie, 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.

Based on answer from @DaoWen , this is my untested solution.

public class MultipleThreadWriter {

private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
private final Lock r = rwl.readLock();
private final Lock w = rwl.writeLock();


public void writeData() {

    r.lock();
    try {   
        //do write stuff    
    } finally {
        r.unlock();
    }

}

public void upgradeSystem() {

    w.lock();
    try {
        //do updates
    } finally {
        w.unlock();
    }

}
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM