【问题标题】:Why didn't Java 8 add `withLock` default methods to the `java.util.concurrent.locks.Lock` interface?为什么 Java 8 没有在 `java.util.concurrent.locks.Lock` 接口中添加 `withLock` 默认方法?
【发布时间】:2014-06-04 09:51:56
【问题描述】:

this question一样,我想知道为什么Java团队没有在Lock接口中添加一些默认方法,像这样:

public default void withLock(Runnable r) {
  lock();

  try {
     r.run();
  } finally {
     unlock();
  }
}

这将允许程序员这样做

public class ThreadSafe {
  // Object requiring protection
  private final List<String> l = new ArrayList<>();
  private final Lock lock = new ReentrantLock();

  public void mutate(String s) {
    lock.withLock(() -> l.add(s));
  }

  public void threadSafeMethod {
    lock.withLock(() -> { System.out.println(l.get(l.size())); });
  }
}

而不是

public void threadSafeMethod {
  lock.lock();
  try {
    System.out.println(l.get(l.size())); 
  } finally { 
    lock.unlock();
  }
}

【问题讨论】:

    标签: locking java-8 default-method


    【解决方案1】:

    这个问题的答案似乎与the linked question 的答案相似——它被认为是“令人讨厌的麻烦”,因为从 lambda 创建的Runnable 的分配成本(参见Brian Goetz's response 到请求)。

    好消息是这个请求有 an open bug,这意味着一旦 JVM 能够可靠地最小化分配成本,Oracle 似乎愿意重新考虑这个决定。

    【讨论】:

    • 作为旁注,Brian 的示例 withLock( () -&gt; { counter++; } ); 不可能是捕获 lambda,因为该示例中的 counter 不能是局部变量。但我们明白了这一点,实际上,你不能在这样的 withLock 中改变本地变量,或者发出 return 和其他提前退出控制语句的限制,可能是反对它的更有力的论据。跨度>
    • @Marko Topolnik:示例() -&gt; counter++ 一个捕获 lambda 但它仅在 counter 是成员变量时才有效,因此 lambda 记住对 @987654332 的不可变引用@(或 static 变量的类)。请注意,如果 counter 是一个局部变量,那么不仅 lambda 不起作用,它还会使整个示例变得毫无意义,因为没有理由对 local 变量的更新应该由 @ 保护987654335@.
    • @Holger 似乎存在术语不一致:我的意思是它不是一个 closure 因为它不会关闭局部变量(我认为这与“捕获 lambda”)。这意味着该示例没有展示任何性能问题,因此无法解释为什么 withLock 未包含在 API 中。如果counter 是本地变量,您的补充说明该示例将无效。
    • @Marko Topolnik:Brian Goetz 的解释针对的问题是,对于当前的 lambda 实现,当 lambda 具有状态 (see my explanation here) 时,每次调用都会创建一个新实例。不管是捕获this 还是counter,在这种情况下有用的lambda 总是有状态,因此每次都会产生一个新实例。所以他关于“捕获”的说法是正确的。但是,当所有其他 API 都忽略它时,我不明白为什么这个小性能问题会推动 API 设计决策……
    • @Holger 一个合理的预期是可以从this 引用的对象访问this 捕获的 lambda,而不涉及任何哈希表支持的 lambda 缓存。另外,我认为您使用的术语“调用站点”不是指调用站点,而是指 lambda 创建站点。
    猜你喜欢
    • 1970-01-01
    • 2018-01-28
    • 1970-01-01
    • 2019-04-02
    • 2016-03-11
    • 2015-12-16
    • 2016-07-20
    • 2015-03-06
    • 1970-01-01
    相关资源
    最近更新 更多