Question

lets make it simple: normally update() is executed by multiple threads. once this is true if(!isSplit && users.size() >= Constants.SPLIT_THRESHOLD) i want that no one is executiong the update() method when the split() functions is celled.

public class Cell {
    private ConcurrentHashMap<Integer, User> users;
    private ConcurrentHashMap<Long, Cell> subCells;
    private boolean isSplit;
    private Lock splitLock;

    public Set<Integer> update(User user){

        //code executed by 1 thread
        if(!isSplit && users.size() >= Constants.SPLIT_THRESHOLD)
        {
            splitLock.lock();
            {
                try
            {
                    split();
                    isSplit = true;
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                finally
                {
                    splitLock.unlock();
                }
            }
        }

        // code executed by multiple threads
        // on users hashmap
    }
    private void merge(){}
    private void split(){}
}
Was it helpful?

Solution 2

I'm not in a position to tell you if your code is currently getting the locking / synchronization correct.

However, under normal circumstances, I'd use a primitive object mutex for something like this:

private final Object splitLock = new Object();

// Use it like this ...
synchronized (splitLock) {
    split();
}

AFAIK, there is no performance advantage in using a ReentrantLock over a primitive object mutex. I'd only recommend using this class if you are going to make use of features that primitive object mutexes don't support;

OTHER TIPS

A general pattern, when locking for write/update, is to acquire the lock first, then check your conditions (that are modified by the write/update), then write.

lock
if(x) {
    write/update
}
unlock

Contrast that with this, which is analogous to the code you have posted:

if(x) {
    lock
    write/update
    unlock
}

x can evaluate to true for thread-1, meanwhile thread-2 executes a write/update causing x to evaluate to false, but thread-1 is already inside the condition, and will execute a write/update anyway. fail.

UPDATE: Responding to updated question.

Check out the javadoc for ReentrantReadWriteLock.

You probably want to isolate your split() method with a write lock (only one thread can acquire), and the remainder of your update method with a read lock (multiple threads can acquire, so long as no one has the write lock).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top