Конвертировать синхронизированные методы в неблокирующий алгоритм

Просто найдите некоторую информацию о неблокирующих алгоритмах, поэтому захотите использовать их на практике. Я изменил некоторый код с синхронизированного на неблокирующий, поэтому хочу спросить, все ли я сделал правильно и сохранил предыдущую функциональность.

синхронизированный код:

protected PersistentState persistentState;
protected ClassConstructor(final ID id)
{
    super(id);
    this.persistentState = PersistentState.UNKNOWN;
}
public final synchronized PersistentState getPersistentState()
{
    return this.persistentState;
}

protected synchronized void setPersistentState(final PersistentState newPersistentState)
{
    if (this.persistentState != newPersistentState)
    {
        this.persistentState = newPersistentState;
        notifyPersistentStateChanged();
    }
}

моя альтернатива неблокирующему алгоритму:

     protected AtomicReference<PersistentState> persistentState;
  protected ClassConstructor(final ID id)
    {
        super(id);
        this.persistentState = new AtomicReference<PersistentState>(PersistentState.UNKNOWN);
    }
   public final PersistentState getPersistentState()
    {
        return this.persistentState.get();
    }

    protected void setPersistentState(final PersistentState newPersistentState)
    {
        PersistentState tmpPersistentState;
        do
        {
            tmpPersistentState = this.persistentState.get();
        }
        while (!this.persistentState.compareAndSet(tmpPersistentState, newPersistentState));
        // this.persistentState.set(newPersistentState); removed as not necessary 
        notifyPersistentStateChanged();
    }

Я все сделал правильно, или я что-то пропустил? Какие-нибудь предложения для кода и использования неблокирующего метода для установки предмета вообще?

1 ответ

Решение

Зависит от того, что вы подразумеваете под thread-safe, Что вы хотите, чтобы два потока пытались писать одновременно? Должен ли один из них, выбранный случайным образом, быть выбран в качестве правильного нового значения?

Это было бы самым простым.

protected AtomicReference<PersistentState> persistentState = new AtomicReference<PersistentState>(PersistentState.UNKNOWN);

public final PersistentState getPersistentState() {
    return this.persistentState.get();
}

protected void setPersistentState(final PersistentState newPersistentState) {
    persistentState.set(newPersistentState);
    notifyPersistentStateChanged();
}

private void notifyPersistentStateChanged() {
}

Это все равно называют notifyPersistentStateChanged во всех случаях, даже если состояние не изменилось. Вам нужно решить, что должно произойти в этом сценарии (один поток делает A -> B, а другой - B -> A).

Однако, если вам нужно только позвонить notify если вы успешно передали значение, вы можете попробовать что-то вроде этого:

 protected void setPersistentState(final PersistentState newPersistentState) {
    boolean changed = false;
    for (PersistentState oldState = getPersistentState();
            // Keep going if different
            changed = !oldState.equals(newPersistentState)
            // Transition old -> new successful?
            && !persistentState.compareAndSet(oldState, newPersistentState);
            // What is it now!
            oldState = getPersistentState()) {
        // Didn't transition - go around again.
    }
    if (changed) {
        // Notify the change.
        notifyPersistentStateChanged();
    }
}
Другие вопросы по тегам