【问题标题】:In Java Concurrency In Practice by Brian Goetz, why is the Memoizer class not annotated with @ThreadSafe?在 Brian Goetz 的 Java Concurrency In Practice 中,为什么 Memoizer 类没有使用 @ThreadSafe 注释?
【发布时间】:2010-12-24 21:19:25
【问题描述】:

Brian Goetz 的 Java Concurrency In Practice 提供了一个用于并发使用的高效可扩展缓存示例。显示类 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());
        }
    }
}

}

【问题讨论】:

    标签: java concurrency thread-safety


    【解决方案1】:

    它看起来确实是线程安全的。如果我没记错的话,在这个特定版本的 Memoizer 中,Goetz 展示了使用 cache.putIfAbsent 来避免缓存的 get 和 put 方法之间的竞争条件。

    正如其他人指出的那样,它可能被遗漏了,您必须依靠书中的评论来判断这是否是“好”版本。

    【讨论】:

      【解决方案2】:

      我想问问 Goetz。这可能只是一个疏忽。

      但是,这些注释的问题在于它们毫无意义。理想情况下,它们需要与自动错误查找器(例如 FindBugs)结合使用,在这种情况下,注释 @Immutable(例如)将允许 FindBugs 打开其检测器以检测字段突变。

      如果没有这样的检查,库的作者很容易将@ThreadSafe@Immutable 附加到一个甚至不是真的类!我不是在暗示故意欺骗,而是在暗示诚实的错误……然而结果是图书馆的消费者不能依赖注释,那有什么意义呢?

      【讨论】:

      • 这些注释并非毫无意义。它们传达了一些信息:例如,一个类应该是线程安全的和/或不可变的。如果您开始在代码中添加这些今天,那么您不仅向从事代码库工作的人传达了意义,而且您将拥有有一天可能会被标记为的代码被 FindBugs 或任何其他工具“破坏”(例如,因为 @Immutable 实际上是可变的)。
      • 注解是元数据。他们自己不做任何事情,但需要其他代码来对他们采取行动。
      猜你喜欢
      • 1970-01-01
      • 2023-03-26
      • 2014-12-28
      • 2018-06-07
      • 2018-06-17
      • 2021-12-02
      • 1970-01-01
      • 2019-02-17
      相关资源
      最近更新 更多