Question reg. holding Locks during invocation of Lambdas
mcnepp02 at googlemail.com
Tue Jun 18 02:11:41 PDT 2013
I noticed that ConcurrentHashMap.computeIfAbsent() invokes the
user-supplied callback while being in a synchronized block.
One of the rules I stick to in programming is "Don't invoke a user-supplied
callback from a library while holding a Lock".
(because it can lead to nasty deadlocks).
If I understand it correctly, the purpose of computeIfAbsent() is delaying
the invocation of a possibly lengthy factory-expression until it has been
determined that a mapping for the key is not already present.
Thus, shouldn't the callback better be called outside any held Locks?
For those interested in more details:
A while back I wrote a class "CacheMap" that serves as a
drop-in-replacement for java.util.Map. Its get(Object key) method invokes a
uses-supplied callback if a mapping is not already present.
In the implementation I went to great lengths to ensure that no Locks are
held while invoking the callback while at the same time guaranteeing
consistency in a multi-threaded scenario.
(The Map-wide Lock is only held for a short duration to atomically check
for the key and put a temporary "factory" object in the internal Map. This
factory object then uses wait/notify to ensure that subsequent threads
requiring the same key will block until the callback has been invoked).
So I know it's possible to do it "correctly". Now I'd be reluctant to
replace my "CacheMap" with JDK's "ConcurrentHashMap" because of the
possible deadlocks waiting to happen.
More information about the lambda-dev