【问题标题】:Why can static and default interface methods not be synchronized but can be strictfp? [duplicate]为什么静态和默认接口方法不能同步但可以是strictfp? [复制]
【发布时间】:2018-05-27 17:01:06
【问题描述】:

为什么静态和默认接口方法不能同步?

人们说同步是一个实现细节。好吧,strictfp 也是一个实现细节,但这并不妨碍在静态和默认接口方法上允许 strictfp。

默认方法是继承的,如果实现接口的类没有覆盖默认方法,让它已经同步可能会很方便。

我猜测 synchronized(以及 strictfp)不是继承的(我在这里吗?),但这并不能解释为什么静态和默认接口方法也允许 strictfp。

【问题讨论】:

  • 这个问题跨越了两个问题的界限。你会在两个副本中找到答案,但我对此并不满意。如果他们必须在两个地方寻找一个答案,那么其他人在寻找答案时会感到脱节。
  • 静态方法和接口方法的原因可能不同:synchronized锁在this上,静态方法中没有this。对于接口,正如其他人指出的那样,它是一个实现细节,不应在方法声明中指定。不确定为什么默认接口方法不允许使用它,因为它确实可能有用,正如您所描述的那样。

标签: java interface


【解决方案1】:

strictfp 关键字可确保您的浮点运算 are consistent across all platformsstricftp 然后成为 JVM 的保证,您的浮点运算在所有平台上都是相同的,并且可以预期浮点运算在整个过程中是可移植的和一致的。

标记为synchronized 的方法实际上是一个实现细节,不能由任何一个接口为其任何实现指定或控制。它被有意排除在默认方法之外,正如Brian Goetz 所解释的那样,因为它们本质上是危险的(强调我的):

...那么,为什么它们很危险?同步是关于锁定的。锁定是关于协调对可变状态的共享访问。每个对象都应该有一个同步策略来确定哪些锁保护哪些状态变量。 (参见 Java 并发实践,第 2.4 节。)

...拥有状态的类可以确定该对象的同步策略。但是接口并不拥有它们所混入的对象的状态。因此,在接口中使用同步方法假设了一个特定的同步策略,但是您没有合理的假设基础,因此很可能使用同步没有提供任何额外的线程安全(您可能正在同步锁错了)。

【讨论】:

    【解决方案2】:

    我认为这是因为如果允许的话:

    interface I {
        static synchronized void x() {
        }
    }
    
    class C implements I {
        synchronized static void y() {
        }
    }
    

    然后两个不同的线程可以进入 C.y() 和 C.x(),因为 x() 在 I.class 上同步,而 y() 在 C.class 上同步。这只是我的猜测

    【讨论】:

    • 如果我们遵循相同的逻辑,那么我们不应该在抽象类或作为父类的任何具体类上允许synchronized
    【解决方案3】:
    class C {
        public synchronized void f () {
        }
    }
    

    一样
    class C {
        public void f () {
            synchronized(this){
            }
        }
    }
    

    如果 f 是静态的,则没有要同步的 this 对象。

    【讨论】:

      猜你喜欢
      • 2019-11-24
      • 1970-01-01
      • 2011-04-03
      • 2012-05-27
      • 1970-01-01
      • 2012-06-05
      • 2011-04-26
      • 2015-03-06
      • 1970-01-01
      相关资源
      最近更新 更多