27

抽象クラスをインスタンス化できないため、ロックするオブジェクトがないため、抽象メソッドを同期できなかったというCodeRanchのスレッドを読んでいました。

抽象クラスは子クラスの定義 (契約) であるため、これは意味がありません。同期されたメソッドの抽象定義はロックする必要はありません。子はロックします。抽象的な見出しが示すのは、子がこのメソッドを同期する必要があることだけです。これに関する私の論理は正しいですか?そうでない場合、誰かが私が間違っている理由を説明できますか?

4

4 に答える 4

35

抽象クラスをインスタンス化できないというコメントはゴミです。抽象化するにはインスタンスメソッドでなければならないことを考えると、ロックされる可能性のある参照が確かに存在します。抽象クラスの具象メソッドは引き続き を参照できますthis。ただし、それでも抽象クラスを同期できる必要があるというわけではありません。

メソッドが同期されるかどうかは、メソッドの実装の詳細です。同期は、宣言的なコントラクトとしてどこにも指定されていません。インターフェースで同期できるわけでもありません。

クラスが提供するスレッドセーフ保証をどのように実装するかは、クラス次第です。抽象クラスが特定のアプローチを義務付けたい場合は、テンプレート メソッド パターンを使用する必要があります。

// I hate synchronizing on "this"
private final Object lock = new Object();

public final void foo() {
    synchronized(lock) {
        fooImpl();
    }
}

protected abstract void fooImpl();

ただし、デッドロックなどの原因となるロック内で「不明な」コードを効果的に呼び出していることを考えると、それ自体はかなり危険です。

于 2012-10-09T18:05:28.197 に答える
9

ロック動作は、契約の一部であってはならないため、抽象メソッドまたはインターフェイス メソッドを使用して指定しないでください。

おそらく、ロック動作は基本的に実装の一部であるという考えでした-異なる実装は異なる方法でロックを実行したいと考えています-そして、その抽象化レベルでそれを指定することは逆効果です.

このキーワードsynchronizedは、特に暗黙的なロック (インスタンス メソッドが呼び出されるオブジェクトのロックを取得する) を実装するためのものであり、そのキーワードが適用されない ReentrantLock などの代替手段を使用してロックを行う方法や、場合によっては CAS またはそれ以外の場合は、ロックを完全に回避してください。

于 2012-10-09T18:02:56.913 に答える
4
synchronized void foo()
{
    body
}

と同等であると定義されています

void foo()
{ 
    synchronized(this)
    {
        body
    }
}

(静的な場合は、代わりにクラスで同期されますthis)

抽象メソッドには本体がないため、synchronizedメソッドのキーワードは未定義です。

于 2012-10-09T18:06:29.140 に答える
3

その背後にあるロジックの 1 つは、そのメソッドを同期するかどうかを実装クラスが決定する必要があるということだと思います。つまり、同期または非同期の実装を提供するかどうかを選択する自由が実装者に与えられます。さらに、クライアントには、スレッドセーフが問題にならない場合に同期のオーバーヘッドを回避するために、非同期バージョンを選択するオプションもあります。

于 2012-10-09T18:06:37.743 に答える