Потокобезопасный держатель для произвольных клонируемых данных - PullRequest
0 голосов
/ 28 марта 2011

У меня есть класс SomeMutableData с публичным clone() методом. Я хочу убедиться, что ни один поток никогда не увидит противоречивое состояние (при условии, что экземпляры будут передаваться только с использованием держателя). Я полагаю, использование синхронизации - это самая безопасная возможность, верно?

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>();
}

1 Ответ

2 голосов
/ 28 марта 2011

Поскольку clone () намного дороже, чем синхронизированный, это вряд ли имеет значение с точки зрения производительности.

Тем не менее, второй пример безопасен для потоков и незначительно быстрее.

единственное отличие состоит в том, что в первом примере вы можете сделать это.(Нравится вам это или нет;)

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);
    }
}
...