Jimmy Page
Jimmy Page

Reputation: 343

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.

Upvotes: 9

Views: 3309

Answers (4)

skaffman
skaffman

Reputation: 403551

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.

Upvotes: 10

user949300
user949300

Reputation: 15729

This is the archetypal case to use a CopyOnWriteArrayList.

"This is ordinarily too costly, but may be more efficient than alternatives when traversal operations vastly outnumber mutations, and is useful when you cannot or don't want to synchronize traversals, yet need to preclude interference among concurrent threads. "

Upvotes: 1

JB Nizet
JB Nizet

Reputation: 691943

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.

Upvotes: 3

Peter Lawrey
Peter Lawrey

Reputation: 533670

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.

Upvotes: 6

Related Questions