I have scenario where i have multiple counters object. Each counters object can be incremented by multiple threads at the same time so there is a set of ReentrantLock for all objects and this works good - each object can be modified only by one thread at given moment.
Here's the catch: there is a process which runs every 15 minutes and collects all counters object, do some calculations and clears counters. This thread is not locking anything so there are situations as below:
In such situations one of the counters object is messed up because at the end clearing operation is discarded and the state of counters are same as before clearing.
What i want to:
I have backup plans:
As you can see i have some options but i'm wondering if there is better way to do this.
UPDATE I was asked for the code so there it is.
Below example of one of the methods that increments counters on object.
public void sipIncomingCall(String objName) {
try {
lock(objName);
Stats stat = getStatisticsForObj(objName);
long l = stat.getSipIncomingConnections().incrementAndGet();
stat.getSipConnectionsSum().incrementAndGet();
LOGGER.debug("incrementing sip incoming connections to {}, objName {}", l, objName);
putStatisticsForObj(objName, stat);
}finally {
unlock(objName);
}
}
lock() and unlock() methods:
private Map<String,ReentrantLock> locks = new ConcurrentHashMap<>();
protected void lock(String key) {
ReentrantLock lock = locks.getOrDefault(key, new ReentrantLock());
lock.lock();
}
protected void unlock(String key){
ReentrantLock lock = locks.get(key);
if(lock!=null){
lock.unlock();
}
}
methods getStatisticsForObj() and putStatisticsForObj():
private MgcfStats getStatisticsForObj(String tgName) {
//get object from local cache (or hazelcast)
return Cluster.getTgStatistics(tgName);
}
private void putStatisticsForObj(String tgName,MgcfStats stats){
//saving to local cache and hazelcast
Cluster.putTgStatistics(tgName,stats);
}
Below is fragment from "clearing_thread" which copies all statistics objects to local map and then clearing statistics in Cluster:
statisticsData.setObjStats(new HashMap<>(Cluster.getTgStatistics()));
Cluster.clearTgStatistics();
You may use ReadWriteLock
.
You still need individual locks for each counter.