首页 > 解决方案 > 从Java中的匿名内部类调用外部同步方法

问题描述

从匿名内部类调用同步方法是否安全且正确?外部类中的锁监视器是否正确获取?

这是代码的一小部分摘录,显示了我的意思。

留下这样的代码是否有任何问题,或者我最好更改它?

class OuterClass {

   public synchronized Object getValue(String id) { .... }

   public synchronized getValueFunction(String id) {
      
      return new GetValueInnerInterface() {
          @Override
          public Object getValueInner(String id) {
              return getValue(id);
          }
      }      
   } 

}

谢谢

标签: javaconcurrencysynchronization

解决方案


synchronized void foo() {
  code();
}

只是语法糖。这与以下内容完全相同:

void foo() {
  synchronized (this) {
    code();
  }
}

一直foo是静态的,在一个名为 的类中class Example {},它是:

static void foo() {
  synchronized (Example.class) {
    code();
  }
}

因此,这意味着将“同步”放在方法上几乎总是错误的。锁是重要的东西,如果你“泄露”它们,那么你需要记录你的锁定行为。通常,您希望您的锁是私有的,这意味着正确的举动通常是:

public class Example {
  private final Object locker = new Object();

  public void doSomethingSynchronized() {
    synchronized (locker) {
      code();
    }
  }
}

但是,如果您真的想使用公共锁(假设Example.class其他代码不受您控制也可以锁定,并且通常this也可用于您直接控制之外的代码),然后确保记录它,这也意味着您必须继续支持锁定行为,因为您永远记录它(嗯,那个,或者破坏向后兼容性)。

鉴于这是它的工作方式,是的,当然,如果您从匿名内部类或其他任何地方调用这些方法,它们将锁定在具有关键字的方法的上下文中this意味着什么(所以,外部的实例,而不是内部的实例)。synchronized

请注意,synchronizedgetValueFunction方法上粘贴 a 似乎没用:该函数所做的任何事情都不需要同步,正如所写的那样。

此外,一般来说,“只是将同步的关键字扔到任何地方,就像它已经过时一样”是实现线程安全的一种非常糟糕的方式(例如,它实际上不会给你线程安全并减慢一切速度)。


推荐阅读