Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I synchronize getter while a setter is working in Java

I am having a multi-thread application using a single static class which provides a list. I want getters of the static class to work freely (not synchronized against each other) but when a setter is working I want all getters to get locked and wait until setter's job is done. I don't want to lock getters when they are called together since it would degrade performance a lot. Getters are called 1,000,000 times per day and setter is only supposed to work once per day.

like image 327
Jimmy Page Avatar asked Nov 19 '11 16:11

Jimmy Page


3 Answers

Consider using a java.util.concurrent.locks.ReadWriteLock implementation, such as ReentrantReadWriteLock (see javadoc)

A ReadWriteLock maintains a pair of associated locks, one for read-only operations and one for writing. The read lock may be held simultaneously by multiple reader threads, so long as there are no writers. The write lock is exclusive.

You would use this instead of synchronized. Your getters would obtain the read lock, then release when they return, e.g.

public String getX() {
    Lock readLock = readWriteLock.readLock();
    readLock.lock();
    try {
        return value;
    } finally {
        readLock.unlock();
    }
}

Similarly for setters methods, but using readWriteLock.writeLock() instead.

The class would have a single ReentrantReadWriteLock object, shared by all getters and setters on each object (or, if you wish, one per getter/setter pair).

It's quite cumbersome, but should give good concurrency. For those reasons, you should only take this on if you really need it, and that means measuring the degraded concurrency you get if you just use vanilla synchronization.

like image 56
skaffman Avatar answered Nov 18 '22 14:11

skaffman


Your setter can take a copy of the data on each update and getters can use the copy. This can be very expensive for the setter, but minimal impact for the getters.

However a synchronized lock can be in the order of 25 to 100 ns. Even if you calling a synchronized method one million times per minute, synchronized may not add enough delay to worry about. At one million per second, it definitely will.

like image 6
Peter Lawrey Avatar answered Nov 18 '22 16:11

Peter Lawrey


I would first synchronize all the accesses, and only optimize if that proves to be a performance problem.

To optimize, you could use a CopyOnWriteArrayList, or a ReadWriteLock. It's hard to give a definitive solution without knowing the context more precisely.

like image 3
JB Nizet Avatar answered Nov 18 '22 16:11

JB Nizet