217

Java 8 では、次のように簡単に記述できます。

interface Interface1 {
    default void method1() {
        synchronized (this) {
            // Something
        }
    }

    static void method2() {
        synchronized (Interface1.class) {
            // Something
        }
    }
}

クラスでも使用できる完全な同期セマンティクスを取得します。synchronizedただし、メソッド宣言で修飾子を使用することはできません。

interface Interface2 {
    default synchronized void method1() {
        //  ^^^^^^^^^^^^ Modifier 'synchronized' not allowed here
    }

    static synchronized void method2() {
        // ^^^^^^^^^^^^ Modifier 'synchronized' not allowed here
    }
}

ここで、 onと onのコントラクトInterface2を確立することを除いて、2 つのインターフェイスは同じように動作すると主張できます。これは、コントラクトよりも少し強力です。もちろん、実装は具体的な実装状態について仮定を行うべきではない、またはそのようなキーワードは単にその重みを引き出すことができないと主張することもできます。method1()method2()Interface1default

質問:

synchronizedJSR-335 専門家グループがインターフェイス メソッドをサポートしないことにした理由は何ですか?

4

2 に答える 2

270

最初は、デフォルトのメソッドで修飾子をサポートしたいのは明白に思えるかもしれませんがsynchronized、そうすることは危険であることが判明したため、禁止されました。

synchronized同期メソッドは、ロック オブジェクトが受信側であるブロックに本体全体が囲まれているかのように動作するメソッドの省略形です。このセマンティクスをデフォルトのメソッドにも拡張することは賢明に思えるかもしれません。結局のところ、それらはレシーバーを持つインスタンス メソッドでもあります。(メソッドは完全に構文の最適化であることに注意してください。synchronizedメソッドは必要ではなく、対応するブロックよりもコンパクトなだけですsynchronized。これはそもそも時期尚早な構文の最適化であり、同期されたメソッドであるという合理的な議論があります。解決するよりも多くの問題を引き起こしますが、その船はずっと前に出航しました。)

では、なぜ彼らは危険なのでしょうか? 同期はロックに関するものです。ロックとは、変更可能な状態への共有アクセスを調整することです。各オブジェクトには、どのロックがどの状態変数を保護するかを決定する同期ポリシーが必要です。( Java Concurrency in Practiceのセクション 2.4 を参照してください。)

多くのオブジェクトは、同期ポリシーとしてJava Monitor パターン(JCiP 4.1) を使用します。このパターンでは、オブジェクトの状態は固有のロックによって保護されます。このパターンには魔法も特別なものもありませんが、便利であり、synchronizedメソッドでキーワードを使用すると、暗黙的にこのパターンが想定されます。

そのオブジェクトの同期ポリシーを決定するのは、状態を所有するクラスです。しかし、インターフェイスは、それらが混在するオブジェクトの状態を所有していません。したがって、インターフェイスで同期メソッドを使用すると、特定の同期ポリシーが想定されますが、想定するための合理的な根拠がないため、同期を使用しても、追加のスレッド セーフはまったく提供されません (間違ったロックで同期している可能性があります)。これにより、スレッド セーフについて何かを行ったという誤った確信が得られ、誤った同期ポリシーを想定していることを示すエラー メッセージが表示されなくなります。

単一のソース ファイルの同期ポリシーを一貫して維持することは、すでに十分に困難です。サブクラスがそのスーパークラスによって定義された同期ポリシーに正しく準拠していることを確認することはさらに困難です。このような疎結合のクラス (インターフェースとそれを実装する可能性のある多くのクラス) の間でこれを行おうとすると、ほとんど不可能になり、エラーが発生しやすくなります。

反対のすべての議論を考えると、何を支持する議論になるでしょうか? それらは主に、インターフェイスをよりトレイトのように動作させることに関するものであるようです。これは理解できる要望ですが、デフォルト メソッドの設計の中心はインターフェイスの進化であり、"Traits--" ではありません。この 2 つを一貫して達成できる場合は、そうしようと努力しましたが、一方が他方と矛盾する場合は、主要な設計目標を優先して選択する必要がありました。

于 2014-05-05T00:50:29.813 に答える