3

ときどき変更したいデータ構造があり、ときどき完全に置き換えたいことがあります。現時点では、これを AtomicReference に保存し、変更する必要がある場合は、置き換えるのではなく、同期ブロック (保存された値ではなく、AtomicReference 自体で同期) を使用しています。

次のようなものです:

public void foo(AtomicReference reference){
    synchronized(reference){
        reference.get()
            .performSomeModification();
    }
}

変更呼び出しは、アトミック参照ではなく、ラップされた値のメンバーであり、独自のスレッド セーフが保証されていないことに注意してください。

これは安全ですか?Findbugs (フリーウェアのコード レビュー ツール) はそれについてこう言っていました特に不変のものとして AtomicReference を参照しているドキュメントも見ました。

これは安全ですか?そうでない場合は、動作についてより確実な独自の参照格納クラスを作成できますが、結論に飛びつきたくありません。

4

2 に答える 2

1

変更可能なアトミック参照は悪い考えですか?

絶対にありません!AtomicReference基になる参照のスレッドセーフでアトミックな更新を提供するように設計されています。実際、AtomicReference の Javadoc の説明は次のとおりです。

アトミックに更新できるオブジェクト参照。

したがって、それらは間違いなく変異するように設計されています!

これは安全ですか?

「安全」の意味と、コードの残りの部分が何をしているかによって異なります。コードのスニペットを分離することについて、本質的に危険なことは何もありません。少し変わっているかもしれませんが、AtomicReference で同期することは完全に有効です。このコードに慣れていない開発者として、同期がオンになっているのを見referenceて、基になるオブジェクトがいつでも置き換えられる可能性があることを意味し、コードが常に「最新」の参照で動作していることを確認したいと思います。

同期の標準的なベスト プラクティスが適用され、それらに違反すると、安全でない動作が発生する可能性があります。たとえば、performSomeModification()はスレッドセーフではないと言っているので、 で同期せずに基になるオブジェクトに別の場所でアクセスすると安全ではなくなりますreference

public void bar(AtomicReference reference) {
    // no synchronization: performSomeModification could be called on the object 
    // at the same time another thread is executing foo()
    reference.get().performSomeModification();

}

アプリケーションで一度に操作できるのは基になるオブジェクトのインスタンスを 1 つだけにする必要があり、参照を .set() するときに同期していない場合も、「安全ではない」可能性があります。

public void makeNewFoo(AtomicReference reference) {
    // no synchronication on "reference", so it may be updated by another thread 
    // while foo() is executing performSomeModification() on the "old" reference
    SomeObject foo = new SomeObject();
    reference.set(foo);
}

AtomicReference で同期する必要がある場合は、そうしてください。完全に安全です。ただし、なぜそれを行っているのかについて、いくつかのコード コメントを追加することを強くお勧めします。

于 2016-09-09T00:49:02.137 に答える