Reputation: 27375
I'm trying to find the most optimal solution for my particular situation.
I currently have the following class:
public class Container
private volatile Date date;
private int amount;
private final Object lock = new Object();
public void update(int amount){
int actualAmount;
if(check(date)){
//do some BULK computation to compute the actualAmount
synchronized(lock){
date = new Date();
this.amount = actualAmount;
}
}
}
private boolean check(Date date){
synchronized(lock){
//reading from the date and returning true if the date is expired
}
}
}
The class represents all updates of amount of money shared by a user group. The group may consist up to 100 users. The amount
field may be updated by any user of the group concurrently.
Calling the update(int)
includes entering two synchronized blocks which is not very good from performance standpoint. Also it may happen that the BULK operation will be computed twice or more times even if there is no need for it. Actually, assume that three threads are trying to acces update()
concurrently. The check(date)
returned true in each of the threads. It doesn't do any harm, but the BULK operation is quite heavy (more thaqn 1 minute). So, it's critical to not perform it even twice if there is no need.
It's not possible to wrap the BULK operation into a synchronized block becuase it includes calling a couple of alien methods. So, I tend to use ReentrantLock
instead of synchronization. The class then may be rewritten as follows:
public class Container
private volatile Date date;
private int amount;
private final Lock lock = new ReentrantLock();
public void update(int amount){
int actualAmount;
lock.lock();
try{
if(check(date)){
//do some BULK computation to compute the actualAmount
date = new Date();
this.amount = actualAmount;
}
} finally {
lock.unlock();
}
}
private boolean check(Date date){
//reading from the date and returning true if the date is expired
}
}
QUESTION: Is such using of ReentrantLock
more efficient in such circumstances than explicit synchronization
.
Upvotes: 0
Views: 182
Reputation: 26926
You can do the same without synchronization.
Synchronization is needed only if a thread needs to know the value of a variable to update it. If the thread only change a variable it is sufficient to define it as volatile.
public class Container
private volatile Date date;
private volatile int amount;
public void update(int amount){
int actualAmount;
if (check(date)) {
//do some BULK computation to compute the actualAmount
date = new Date();
this.amount = actualAmount;
}
}
private boolean check(Date date) {
//reading from the date and returning true if the date is expired
}
}
NOTE: A synchronization can be necessary if the amount depends on the actual amount value. A synchronization for date is not necessary
Upvotes: 1