Конвертировать синхронизированные методы в неблокирующий алгоритм
Просто найдите некоторую информацию о неблокирующих алгоритмах, поэтому захотите использовать их на практике. Я изменил некоторый код с синхронизированного на неблокирующий, поэтому хочу спросить, все ли я сделал правильно и сохранил предыдущую функциональность.
синхронизированный код:
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();
}
}