В параллельности Java на практике Брайан Гетц, почему класс Memoizer не аннотирован @ThreadSafe? - PullRequest
9 голосов
/ 25 декабря 2010

Java Concurrency на практике Брайан Гетц (Brian Goetz) представляет пример эффективного масштабируемого кэша для одновременного использования. Окончательная версия примера, показывающая реализацию для класса Memoizer (стр. 108), показывает такой кэш. Мне интересно, почему класс не помечен @ThreadSafe? Клиент, класс Factorizer, кеша правильно помечен @ThreadSafe. В приложении говорится, что если класс не аннотирован ни @ThreadSafe, ни @Immutable, то следует предположить, что он не является потокобезопасным. Тем не менее, Memoizer кажется поточно-ориентированным.

Вот код для 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());
        }
    }
}

}

Ответы [ 2 ]

1 голос
/ 30 декабря 2010

Это, конечно, выглядит поточно-ориентированным.Если я правильно помню, в этой конкретной версии Memoizer Гетц демонстрировал использование cache.putIfAbsent, чтобы избежать условия гонки между методами get и put кеша.

Как указали другие, возможно, он был опущен, и вам придется полагаться на комментарий в книге, чтобы узнать, является ли это «хорошей» версией.

0 голосов
/ 25 декабря 2010

Спроси у Гетца, наверное. Это может быть просто недосмотр.

Однако проблема с этими аннотациями в том, что они бессмысленны. В идеале их нужно использовать вместе с автоматическим поиском ошибок, таким как FindBugs, и в этом случае аннотация @Immutable (например) позволит FindBugs включить свой детектор для мутаций поля.

Без такой проверки автору библиотеки легко присоединить @ThreadSafe или @Immutable к классу, даже если это не так! Я не предлагаю преднамеренный обман, а скорее честные ошибки ... тем не менее, результат в том, что потребитель библиотеки не может зависеть от аннотаций, так какой в ​​этом смысл?

...