[解決済み】Java 8のインターフェースメソッドで "synchronized "が使えない理由は?
質問
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
}
}
さて、この2つのインターフェイスの動作は
Interface2
を確立します。
契約
について
method1()
と
method2()
よりも少し強いです。
Interface1
のようになります。もちろん、次のように主張することもできます。
default
の実装は、具体的な実装の状態についていかなる仮定もするべきではないし、そのようなキーワードは単にその重みを引き出さないだろう。
質問です。
JSR-335エキスパートグループが
synchronized
をインターフェイスメソッドに追加することはできますか?
どのように解決するのですか?
をサポートすることは、一見、当然のことのように思えます。
synchronized
という修飾子をデフォルトのメソッドにつけることは危険であることがわかり、禁止されました。
同期されたメソッドとは、あたかも本体全体が
synchronized
ブロックのロックオブジェクトがレシーバーとなります。 このセマンティクスをデフォルト・メソッドにも拡張することは賢明と思われるかもしれません。 (結局のところ、彼らもレシーバーを持つインスタンス・メソッドなのです(ただし
synchronized
メソッドは、完全に構文的な最適化であり、必要なものではなく、対応する
synchronized
ブロックがあります。 そもそも構文の最適化が時期尚早であり、同期されたメソッドは解決するよりも多くの問題を引き起こすという合理的な議論がありますが、その船はずっと前に出航しています)。
では、なぜ危険なのでしょうか? 同期とは、ロックすることです。 ロックとは、変更可能な状態への共有アクセスを調整することです。 各オブジェクトは、どのロックがどの状態変数を保護するかを決定する同期化ポリシーを持っている必要があります。 (参照 Java並行処理の実際 2.4節参照)
多くのオブジェクトは、同期化ポリシーとして
Java Monitorパターン
(JCiP 4.1) では、オブジェクトの状態はその固有ロックによって保護されます。 このパターンには何のマジックも特別なものもありませんが、便利です。
synchronized
キーワードは、暗黙のうちにこのパターンを想定しています。
そのオブジェクトの同期ポリシーを決定するのは、その状態を所有するクラスなのです。 しかし、インターフェースは、それが混在しているオブジェクトの状態を所有しません。 ですから、インターフェイスの中で同期化されたメソッドを使うことは、特定の同期化ポリシーを仮定することになりますが、それはあなたが仮定するための合理的な根拠がないため、同期化の使用は何の追加スレッド安全性を提供しない(間違ったロックで同期化しているかもしれない)ということになるかもしれません。 この場合、スレッドセーフについて何かをしたという誤った確信を持つことになり、エラーメッセージも間違った同期ポリシーを仮定していることを教えてくれません。
単一のソースファイルに対して同期ポリシーを一貫して維持することは既に十分困難です。サブクラスがそのスーパークラスによって定義された同期ポリシーを正しく遵守することはさらに困難です。 このような疎結合のクラス(インターフェイスとそれを実装する多くのクラス)の間で同期を行おうとすると、ほとんど不可能であり、非常にエラーを起こしやすいでしょう。
これらの反対論があるとして、賛成論は何だろう? ほとんどの場合、インターフェイスをより特質に近い形で動作させることを目的としているようです。 これは理解できる願望ですが、デフォルトメソッドの設計の中心はインターフェイスの進化であって、"Trait--"ではないのです。 この2つが一貫して達成できるところでは、そうするように努めましたが、一方が他方と対立するところでは、主要な設計目標を優先して選択しなければなりませんでした。
関連
-
[解決済み] double 型を Int 型に変換、切り捨て
-
[解決済み] JavaにおけるHashMapとHashtableの違いは何ですか?
-
[解決済み] Javaにおけるpublic、protected、package-private、privateの違いは何ですか?
-
[解決済み] 特定のUnicode文字を含むコメントでのJavaコードの実行が許可されているのはなぜですか?
-
[解決済み] Javaクラスにおけるcanonical name、simple name、class nameの違いは何ですか?
-
[解決済み] Java 8のmap()メソッドとflatMap()メソッドの違いは何ですか?
-
[解決済み] なぜJavaでは静的メソッドを抽象化できないのですか?
-
[解決済み] なぜJava 8のOptionalは引数で使ってはいけないのか
-
[解決済み] Java 8のインターフェイスメソッドで "final "が使えないのはなぜですか?
-
[解決済み】KotlinでJavaの静的メソッドに相当するものは何ですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] Jdbctemplate の文字列に対するクエリです。EmptyResultDataAccessException: 不正な結果サイズ:期待値1、実際0
-
[解決済み] この配列の中の数字を入れ替えるには、何が足りないのでしょうか?ジャバ
-
[解決済み] Java Genericメソッドをstaticにするには?
-
[解決済み] なぜJPAには@Transientアノテーションがあるのですか?
-
[解決済み] javax.mail.MessagingException: SMTPホストに接続できませんでしたか?
-
[解決済み] java.lang.ClassCastException: java.lang.Long を java.lang.Integer にキャストできない(java 1.6
-
[解決済み] 文字列の長さに応じて文字列をトリミングする
-
[解決済み] 文字列の巻き方
-
[解決済み] Javaでdoubleをfloatに変換する
-
[解決済み] Java 8のインターフェイスメソッドで "final "が使えないのはなぜですか?