Reputation: 946
Is the following code thread safe?
HashMap<Integer, HashMap<Integer, Double>> hMap = new HashMap<Integer, HashMap<Integer, Double>>();
ExecutorService executor = Executors.newFixedThreadPool(threads);
// the next line is new
ArrayList<Future<Double>> results = new ArrayList<Future<Double>>();
for (Integer i = 0; i < iBound; i++) {
hMap.put(i, new HashMap<Integer, Double>());
for (Integer j = 0; j < jBound; j++) {
SomeCallable task = new SomeCallable(i, j);
Future<Double> result = executor.submit(task);
results.add(result); // hMap.get(i).put(j, result.get());
}
}
executor.shutdown();
executor.awaitTermination(Integer.MAX_VALUE, TimeUnit.SECONDS);
// the next lines are new
int index = 0;
for (Integer i = 0; i < iBound; i++) {
hMap.put(i, new HashMap<Integer, Double>());
for (int j = 0; j < jBound; j++) {
hMap.get(i).put(j, results.get(index).get());
index++;
}
}
I would say yes, since different threads work with different keys in the hash maps. I have tested this and compared hMap
that is obtained in the multi-thread scenario to the hMap
that is obtained in the following way:
HashMap<Integer, HashMap<Integer, Double>> hMap = new HashMap<Integer, HashMap<Integer, Double>>();
for (Integer i = 0; i < iBound; i++) {
hMap.put(i, new HashMap<Integer, Double>());
for (Integer j = 0; j < jBound; j++) {
SomeCallable task = new SomeCallable(i, j);
hMap.get(i).put(j, task.call());
}
}
I varied the number of threads from 2 to 20 and was changing the time complexity ofSomeCallable.call
. The bounds iBound
and jBound
were set to 500
.
There were no differences between hMap
s, but I want to be sure.
Upvotes: 1
Views: 201
Reputation: 9348
As long as SomeCallable
does not internally access the hMap
instance variable (and is inherently thread safe itself), then this code is safe. We can safely assume that because all manipulations done to hMap
come from the same thread (each and every put / get come from the thread that performs the loop).
On the other hand, there is no real point in executing all this in a threaded manner if after submitting each task, one immediately waits for this task's completion. You might as well use your second code sample, because in practice, your first only ever uses one thread at a time.
And maybe if you actually start using threading in a more "usefull" way, then you HashMap usage may become unsafe.
Upvotes: 4
Reputation: 1033
I'd recommend using a ConcurrentHashMap instead. All protections are in place by default.
Upvotes: 1