3

simplex++はアトミック操作ではないことが知られていますが、実際には読み取り-増分-書き込み操作です。そのため、同期する必要があります。しかし、どうget()ですか?同期する必要があることも読みましたが、誰かが理由を説明してもらえますか?関係を導入してメモリ整合性エラーを回避するにはhappens-beforeget()複数のスレッドによって頻繁に呼び出され、値がめったに変更されない状況についてはどうでしょうか。synchronized get()それらを遅くしていませんか?そのシナリオで同期を実現する他の方法はありますか(AtomicIntegerを使用しない)?volatileキーワードはここで機能しますか?

public class Counter {
    private int value;

    public synchronized int get() { return value; }
    public synchronized int increment() { return ++value; }
    public synchronized int decrement() { return --value; }
}

ありがとう!

編集:

はっきりさせておきたい。使用volatileするということは、そのキーワードを導入し、メソッドで削除することを意味しましsynchronizedget()。多くのスレッドが値を読み取っていて、1つが値を変更することはめったにない場合、スレッドセーフになるだけでなく、より効率的になるかどうか疑問に思いました。

4

4 に答える 4

10

そのシナリオで同期を実現する他の方法はありますか(AtomicIntegerを使用しない)?

まず、AtomicInteger可能であれば使用する必要があります。なぜ使わないのかわかりません。

volatileキーワードはここで機能しますか?

はい。ただし++AtomicIntegerロックせずに安全な増分を提供します。(なんらかのクレイジーな理由で)自分でロールしたい場合は、ブロッキングが必要になるか、AtomicInteger内部スピンメカニズムを複製する必要があります。

しかし、get()はどうですか?同期する必要があることも読みましたが、誰かが理由を説明してもらえますか?

AtomicIntegerをラップしvolatile intてその機能を提供します。フィールドにアクセスするとvolatile、メモリバリアも越えますget()。別のスレッドが値を更新した場合に、を呼び出しているスレッドが更新を確認できるようにするには、そのメモリバリアを越える必要がありますget()。そうしないと、スレッドが古い値で動作している可能性があります。

于 2012-10-04T16:16:24.750 に答える
1

不揮発性の値を繰り返し読み取る場合、JVMは値をレジスタにキャッシュでき、変更が表示されない可能性があります。

これを回避する方法は、値を揮発性にすることです。

ただし、パフォーマンスが懸念される場合は、ロックレスのAtomicIntegerを使用してください。

于 2012-10-04T16:19:19.587 に答える
0

しかし、get()はどうですか?同期する必要があることも読みましたが、誰かが理由を説明してもらえますか?

同期されていない場合、スレッドが操作get()を実行している間、どのスレッドもそれを呼び出すことができると仮定します。set()

ここで、スレッドBがset()操作を実行して、フィールドの値aを5に設定しているとします。ここで、2つのスレッドが値aを読み取っているとします。1つのスレッドはset操作が完了する前に読み取り、他のスレッドは後に読み取ります。動作を設定します。

したがって、両方のスレッドの値は異なります。したがって、フィールドの状態に一貫性がありませんa

ここで、get()メソッドが同期されていると仮定します。次に、スレッドが値を設定しているget()場合、操作が完了しない限り、スレッドは操作を呼び出すことができませんset()。したがって、すべてのスレッドが同じ値を取得します。

于 2012-10-04T16:21:20.043 に答える
0

しかし、get()はどうですか?同期する必要があることも読みましたが、誰かが理由を説明してもらえますか?発生前の関係を導入してメモリ整合性エラーを回避するには?

はい、同期する必要があります。そうでない場合は、インクリメント/デクリメントと同じように、古い値を使用している可能性があります。

get()が複数のスレッドによって頻繁に呼び出され、値がめったに変更されない状況についてはどうでしょうか。同期されたget()はそれらを遅くしていませんか?

競合のないロックは非常に安価です。同時取得の場合でも、コストは全体的なパフォーマンスにあまり影響しない可能性があります。volatileここでは機能しますが、AtomicIntegerパフォーマンス上の理由で使用しない必要はない場合があります。

そのシナリオで同期を実現する他の方法はありますか(AtomicIntegerを使用しない)?volatileキーワードはここで機能しますか?

はい、そうなると思います。

于 2012-10-04T16:21:44.783 に答える