【问题标题】:Call outer synchronized method from anonymous inner class in Java从Java中的匿名内部类调用外部同步方法
【发布时间】:2021-04-30 04:11:22
【问题描述】:

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

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

这样留下代码有什么问题吗?还是我最好改一下?

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);
          }
      }      
   } 

}

谢谢

【问题讨论】:

    标签: java concurrency synchronization


    【解决方案1】:
    synchronized void foo() {
      code();
    }
    

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

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

    如果foo 是静态的,并且在名为class Example {} 的类中,它是以下的缩写:

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

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

    public class Example {
      private final Object locker = new Object();
    
      public void doSomethingSynchronized() {
        synchronized (locker) {
          code();
        }
      }
    }
    

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

    鉴于它是这样工作的,是的,当然,如果您从匿名内部类或其他任何地方调用这些方法,它们将锁定 this 的含义在带有 synchronized 关键字的方法(因此,是外部实例,而不是内部实例)。

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

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

    【讨论】:

      猜你喜欢
      • 2012-02-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-05
      相关资源
      最近更新 更多