开发者

In Java Concurrency In Practice by Brian Goetz, why is the Memoizer class not annotated with @ThreadSafe?

开发者 https://www.devze.com 2023-01-31 22:36 出处:网络
Java Concurren开发者_运维问答cy In Practice by Brian Goetz provides an example of a efficient scalable cache for concurrent use. The final version of the example showing the implementation for class M

Java Concurren开发者_运维问答cy In Practice by Brian Goetz provides an example of a efficient scalable cache for concurrent use. The final version of the example showing the implementation for class Memoizer (pg 108) shows such a cache. I am wondering why the class is not annotated with @ThreadSafe? The client, class Factorizer, of the cache is properly annotated with @ThreadSafe. The appendix states that if a class is not annotated with either @ThreadSafe or @Immutable that it should be assumed that it isn't thread safe. Memoizer seems thread-safe though.

Here is the code for Memoizer:

public class Memoizer<A, V> implements Computable<A, V> {
private final ConcurrentMap<A, Future<V>> cache
    = new ConcurrentHashMap<A, Future<V>>();
private final Computable<A, V> c;

public Memoizer(Computable<A, V> c) { this.c = c; }

public V compute(final A arg) throws InterruptedException {
    while (true) {
        Future<V> f = cache.get(arg);
        if (f == null) {
            Callable<V> eval = new Callable<V>() {
                public V call() throws InterruptedException {
                    return c.compute(arg);
                }
            };
            FutureTask<V> ft = new FutureTask<V>(eval);
            f = cache.putIfAbsent(arg, ft);
            if (f == null) { f = ft; ft.run(); }
        }
        try {
            return f.get();
        } catch (CancellationException e) {
            cache.remove(arg, f);
        } catch (ExecutionException e) {
            throw launderThrowable(e.getCause());
        }
    }
}

}


It certainly looks thread-safe. If I recall correctly, in this particular version of Memoizer, Goetz was showing the use of cache.putIfAbsent to avoid a race condition between the get and put methods of the cache.

As the others have pointed out, it may have been left out and you'll have to rely on the commentary in the book to see whether this is the 'good' version.


Ask Goetz I guess. It may just be an oversight.

However, the problem with those annotations is they are meaningless. Ideally they need to be used in conjunction with an automated bug finder such as FindBugs, in which case the annotation @Immutable (for example) would allow FindBugs to turn on its detector for field mutations.

Without such checking, it's easy for the author of a library to attach @ThreadSafe or @Immutable to a class when it's not even true! I'm not suggesting deliberate deception, but rather honest mistakes... nevertheless the result is that a consumer of the library cannot depend on the annotations, so what's the point?

0

精彩评论

暂无评论...
验证码 换一张
取 消