0

ノンブロッキングアルゴリズムについていくつかの情報を見つけて、実際に使用します。私はいくつかのコードを同期から非ブロックに変更したので、すべてのことを正しく行い、以前の機能を保存しているかどうか尋ねたいと思います。同期メソッドをノンブロッキングアルゴリズムに変換する

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

私が正しく、すべてをやったか、または私は何かを逃した?コード同期

コードに対する提案と一般的にabjectを設定するためのノンブロッキングメソッドの使用

+1

「this.persistentState.set(newPersistentState)」をのcompareAndSetの更新などをpersistentStateの値 – hahn

+0

compareAndSetは、値をnewPersistentStateに設定した後にのみwhileループから抜け出すため、newPersistentStateに再度設定する必要はありません。それが必要だった場合、これはチェック・ストライクの方法であり、古くなったデータの問題が発生しがちです。ありがたいことに、そうではありません。 – Madhusudhan

答えて

3

thread-safeの意味に依存します。 2つのスレッドが同時に書き込もうとすると、何が起こりたいですか?ランダムに選ばれた1人を正しい新しい値として選択する必要がありますか?

これは簡単なことです。

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を呼び出します。そのシナリオで何が起こるべきかを決める必要があります(1つのスレッドはA→B、もう1つは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(); 
    } 
} 
+0

変更があった場合にのみ通知する必要があります。 Btw、スレッドが同じ値を設定したいのであれば私の場合は無限ループになるでしょうか? – Edgar

+0

@エドガー - いいえ。 tmoPersistentStateがnewPersistentStateと同じ場合、ループは正常に動作します。 this.persistentStateがtmpPersistentStateと同じである限り、trueとbreakoutを返します。無限ループはありません。 – Madhusudhan

関連する問題