Closed jasontedor closed 9 years ago
There are two pull requests open to address this issue. The first is #14068 which relaxes the constraint that Cache#computeIfAbsent
be called at most once per key. The second is #14091 which changes the synchronization mechanism to be the key itself so that loading does not occur under the segment lock.
Only one of these two pull requests should be merged into master but given the feedback on #14068 from @jpountz I wanted to explore a different approach for solving the deadlock issue.
The current implementation of
Cache#computeIfAbsent
can lead to deadlocks in situations where dependent key loading is occurring. This is the case because of the locks that are taken to ensure that the loader is invoked at most once per key. In particular, consider two threadst1
andt2
invoking this method for keysk1
andk2
which will both trigger dependent calls toCache#computeIfAbsent
for keyskd1
andkd2
. In cases whenk1
andkd2
and in the same segment, andk2
andkd1
are in the same segment then:t1
locks the segment fork1
t2
locks the segment fork2
t1
blocks waiting for the lock for the segment forkd1
t2
blocks waiting for the lock for the segment forkd2
is a deadlock. This unfortunate situation surfaced in a failed build.