1

私は同期での作業に慣れていません。次のスニペットは正しく見えますか?

public void setNewSessionListener(NewSessionListener newSessionListener) {
    if (this.newSessionListener != null)
        synchronized (this.newSessionListener) {
            this.newSessionListener = newSessionListener;
        }
    else
        this.newSessionListener = newSessionListener;
}

具体的には、null チェックを実行する必要がありますか? 私は、そのコードに根本的な問題があると感じています。

4

4 に答える 4

3

2つの間違いがあります。1 つ目は、同期が必要なフィールドにアクセスする場合、常に同じロックを保持してアクセスする必要があることです。また、フィールドがnullかどうかを確認し、同じ同期ブロック内のフィールドに書き込む必要があります。そうしないと、フィールドに何かを書き込むときに、すでにnullではない可能性があるためです。

2 つ目は、変更されないもの、つまり static final フィールドまたはインスタンス自体で同期するのが最善であるということです。たとえば、この目的専用のロック オブジェクトを作成できます。

private static final Object LOCK = new Object();

そして、次のように記述します。

synchronized (LOCK) {
    if (this.newSessionListener == null) this.newSessionListener = newSessionListener;
}
于 2012-06-24T22:31:29.483 に答える
2

あなたの気持ちは正しいです。synchronizedブロック内で null チェックを行う必要があります。そうしないと、ブロックは二重の初期化を防ぎません。さらに、変更しようとしているものを同期するべきではありませんthis.newSessionListener。ブロックのスコープ全体に留まるオブジェクト (参照) を選択してください。これは、任意の時点で 1 つのスレッドだけがこのコード ブロックに入ることができることを保証する唯一の方法です。これを実現する典型的な方法はsynchronizeonthisです。private finalまたは、この目的のために保持されているオブジェクトを同期することもできます。

ifさらに、最終的にはブランチとブランチの両方で同じ割り当てを実行することになりますがelse、これはおそらくあなたが望むものではありません。

于 2012-06-24T22:31:06.107 に答える
1

これは、少なくとも非常に悪い考えです。次に割り当てるオブジェクトで同期しています。

同期を使用しているため、これは非同期で呼び出され、別のスレッドがこのコード内にあるときに、あるスレッドによって呼び出される可能性があると想定しています。その場合、共通オブジェクトをロックしているのではなく、その時点で保持している値をロックしています。

おそらく、そして私はおそらく強調しますが、あなたは同期することができます(これ)。これにより、この特定のオブジェクトに対するこのメソッドへのすべての呼び出しが確実に同期されます。また、このクラスの他のインスタンスへの呼び出しは、その他のオブジェクトに対してロックされますが、インスタンス間ではロックされません。

インスタンス化されたすべてのオブジェクト間で同期したい場合は、synchronized (YourClass) を呼び出します。

于 2012-06-24T22:35:17.270 に答える
1

別の可能性があります(同期ブロックよりも明示的なロックを好む傾向があります):

private ReentrantLock lock = new ReentrantLock();

lock.lock();
try {
  // do your synchronized code here. 
}
finally {
  lock.unlock();
}

あなたのコードを見るだけでは、なぜ if ブロックがあるのか​​ わかりません。あるケースでは同期していて、他のケースでは同期していないのはなぜですか? 特に、どちらの場合も同じ割り当てを行っていることを考えると?

于 2012-06-25T10:43:05.147 に答える