How do I make the following class threadsafe?
public class Helper
{
private static Map<String,String> map = null;
public static init()
{
map = new HashMap<String,String>();
// some loading stuff
}
public static getMap()
{
if(map==null) init();
return new HashMap<String,String>(map);
}
}
My ideas so far:
-
Make getMap() synchronized.
Problem: Makes the program slower than necessary, because syncronization is only needed at the start of the program and then never again. -
Use a lock. The problem is that the method “isLocked” which I use here doesn’t exist. So what would be the best solution?
public class Helper { private static Map<String,String> map = null; private static Lock lock = new ReentrantLock(); public static init() { lock.lock(); map = new HashMap<String,String>(); // some loading stuff lock.unlock(); } public static getMap() { synchronized {if(map==null) init();} while(lock.isLocked()) {Thread.wait(1);] return new HashMap<String,String>(map); }}
P.S.: Sorry for the second source code display problem. There seems to be a bug with using code after an enumeration.
P.P.S.: I know HashMap isn’t thread safe. But that only means that I cannot write in parallel, reading shouldn’t be a problem, should it?
P.P.P.S.: My final version (just the inner class), following John Vint:
protected static class LazyLoaded
{
static final Map<String,String> map;
static
{
Map<String,String> mapInit = new HashMap<>();
// ...loading...
map = Collections.unmodifiableMap(mapInit);
}
}
I would delegate to a child class
Because class loading is thread-safe and occurs only once this will allow you to lazily initialize your Map.