Reputation: 39
The someParameters hashmap is loaded from a .csv file every twenty minutes or so by one thread and set by the setParameters method.
It is very frequently read by multiple threads calling getParameters: to perform a lookup translation of one value into a corresponding value.
Is the code unsafe and/ or the "wrong" way to achieve this (particularly in terms of performance)? I know about ConcurrentHashMap but am trying to get a more fundamental understanding of concurrency, rather than using classes that are inherrently thread-safe.
One potential risk I see is that the object reference someParameters could be reset whilst another thread is reading the copy, so the other thread might not have the latest values (which wouldn't matter to me).
public class ConfigObject {
private static HashMap<String, String> someParameters = new HashMap<String, String>();
public HashMap<String, String> getParameters(){
return new HashMap<String, String>(someParameters);
//to some thread which will only ever iterate or get
}
public void setParameters(HashMap<String, String> newParameters){
//could be called by any thread at any time
someParameters = newParameters;
}
}
Upvotes: 1
Views: 249
Reputation: 115
There are two problems here
someParameters
after update might not be visible to other thread, to fix this mark someParameters
as volatile
.Collections.unmodifiableMap()
this just wrap original map and disallowing put/remove method.Upvotes: 2
Reputation: 14348
If I understand your problem correctly, you need to change/replace many parameters at once (atomically). Unfortunately, ConcurrentHashMap
doesn't support atomic bulk inserts/updates.
To achieve this, you should use shared ReadWriteLock
. Advantage comparing to Collections.synchronized...
is that concurrent reads can be performed simultaneously: if readLock
is acquired from some thread, readLock().lock()
called from another thread will not block.
ReadWriteLock lock = new ReadWriteLock();
// on write:
lock.writeLock().lock();
try {
// write/update operation,
// e. g. clear map and write new values
} finally {
lock.writeLock().unlock();
}
// on read:
lock.readLock().lock();
try {
// read operation
} finally {
lock.readLock().unlock();
}
Upvotes: 1