Do I need to perform double-check locking control in my getTask method?
You don't need to do double-checked locking (DCL) here. (In fact, it is very rare that you need to use DCL. In 99.9% of cases, regular locking is just fine. Regular locking on a modern JVM is fast enough that the performance benefit of DCL is usually too small to make a noticeable difference.)
However, synchronization is necessary unless you declared tasksCache
to be final
. And if tasksCache
is not final
, then simple locking should be just fine.
I know ConcurrentHashMap is thread-safe for read operations ...
That's not the issue. The issue is whether reading the value of the taskCache
reference is going to give you the right value if the TaskLauncher
is created and used on different threads. The thread-safety of fetching a reference from a variable is not affected one way or another by the thread-safety of the referenced object.
But what about the isDone() method of Future?
Again ... that has no bearing on whether or not you need to use DCL or other synchronization.
For the record, the memory semantics "contract" for Future
is specified in the javadoc:
"Memory consistency effects: Actions taken by the asynchronous computation happen-before actions following the corresponding Future.get() in another thread."
In other words, no extra synchronization is required when you call get()
on a (properly implemented) Future
.
How do you chose the right lock object in a synchronized block?
The locking serves to synchronize access to the variables read and written by different threads while hold the lock.
In theory, you could write your entire application to use just one lock. But if you did that, you would get the situation where one thread waits for another, despite the first thread not needing to use the variables that were used by the other one. So normal practice is use a lock that is associated with the variables.
The other thing you need to be ensure is that when two threads need to access the same set of variables, they use the same object (or objects) as locks. If they use different locks, then they don't achieve proper synchronization ...
(There are also issues about whether lock on this
or on a private lock, and about the order in which locks should be acquired. But these are beyond the scope of the question you asked.)
Those are the general "rules". To decide in a specific case, you need to understand precisely what you are trying to protect, and choose the lock accordingly.