0

SomeMutableDatapublicclone()メソッドを持つクラスがあります。一貫性のない状態がスレッドに表示されないようにしたいと思います (インスタンスがホルダーのみを使用して渡されると仮定します)。同期を使用することが最も安全な可能性だと思いますよね?

public final class ThreadSafeHolder {
    public ThreadSafeHolder(SomeMutableData data) {
        storeData(data);
    }

    public synchronized SomeMutableData cloneData() {
        return data.clone();
    }
    public synchronized void storeData(SomeMutableData data) {
        this.data = data.clone();
    }

    private SomeMutableData data;
}

以下は最初のアプローチと同じくらい安全ですか?

public final class ThreadSafeHolder2 {
    public ThreadSafeHolder2(SomeMutableData data) {
        storeData(data);
    }

    public SomeMutableData cloneData() {
        return data.get().clone();
    }
    public void storeData(SomeMutableData data) {
        this.data.set(data.clone());
    }

    private final AtomicReference<SomeMutableData> data
        = new AtomicReference<SomeMutableData>();
}
4

1 に答える 1

2

clone() は synchronized よりもはるかにコストがかかるため、パフォーマンスの観点からはほとんど問題になりません。

ただし、2 番目の例はスレッド セーフであり、わずかに高速です。

唯一の違いは、最初の例でこれを実行できることです。(これが好きかどうかにかかわらず;)

synchronized(theHolder) {
    SomeMutableData smd = theHolder.cloneData();
    smd.updateIt();
    theHolder.storeData(smd);
}

ところで:ホルダーがラッピングしているタイプを拡張する必要はないと思います。

編集: より GC に適した方法は、次のアプローチを使用することです。データの設定または取得のいずれかでオブジェクトが作成されないように copyFrom() を記述できます。

public final class ThreadSafeHolder {
    private final SomeMutableData data = new SomeMutableData();

    public ThreadSafeHolder(SomeMutableData data) {
        copyFrom(data);
    }

    public synchronized void copyTo(SomeMutableData data) {
        data.copyFrom(this.data);
    }

    public synchronized void copyFrom(SomeMutableData data) {
        this.data.copyFrom(data);
    }
}
于 2011-03-28T16:44:13.927 に答える