Java Reference
In-Depth Information
ished, as in Memoizer2 ). If not, it creates a FutureTask , registers it in the Map , and
starts the computation; otherwise it waits for the result of the existing computation. The res-
ult might be available immediately or might be in the process of being computed—but this is
transparent to the caller of Future.get .
The Memoizer3 implementation is almost perfect: it exhibits very good concurrency
(mostly derived from the excellent concurrency of ConcurrentHashMap ), the result is
returned efficiently if it is already known, and if the computation is in progress by another
thread, newly arriving threads wait patiently for the result. It has only one defect—there is
still a small window of vulnerability in which two threads might compute the same value.
This window is far smaller than in Memoizer2 , but because the if block in compute is
still a nonatomic check-thenact sequence, it is possible for two threads to call compute with
the same value at roughly the same time, both see that the cache does not contain the desired
value, and both start the computation. This unlucky timing is illustrated in Figure 5.4 .
Figure 5.4. Unlucky Timing that could Cause Memoizer3 to Calculate the Same Value Twice.
Search WWH ::




Custom Search