0

Finden Sie nur einige Informationen über nicht blockierende Algorithmen, also wollen Sie sie in der Praxis verwenden. Ich habe den Code von synchron auf nicht blockierend geändert, also möchte ich fragen, ob ich alles richtig gemacht und die vorherige Funktionalität gespeichert habe.Konvertieren Sie synchronisierte Methoden zu nicht blockierenden Algorithmus

synchronisierten Code:

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

meine Alternative in nicht-blockierenden Algorithmus:

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

Muss ich habe alles richtig gemacht, oder ich etwas verpasst? Irgendwelche Vorschläge für den Code und die Verwendung der nicht blockierenden Methode für das Setzen von abject im Allgemeinen?

+1

Sie nicht „this.persistentState.set (newPersistentState)“ als compareAndSet Updates verwenden sollten Wert von persistentState – hahn

+0

Das compareAndSet wird aus der while-Schleife erst dann ausbrechen, nachdem der Wert auf newPersistentState festgelegt wurde, und es daher nicht erneut auf newPersistentState festgelegt wird, wie bereits erwähnt. Wenn es erforderlich wäre, dann wäre dies ein Check-take-Act-Weg, der anfällig für veraltete Datenprobleme ist. Zum Glück ist es nicht. – Madhusudhan

Antwort

3

Hängt davon ab, was Sie unter thread-safe verstehen. Was möchten Sie tun, wenn zwei Threads gleichzeitig versuchen zu schreiben? Sollte einer von ihnen zufällig ausgewählt werden, als der richtige neue Wert gewählt werden?

Dies wäre es am einfachsten.

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

in allen Fällen noch nennen Dies würde notifyPersistentStateChanged, auch wenn der Zustand nicht geändert hat. Sie müssen entscheiden, was in diesem Szenario passieren soll (ein Thread macht A -> B und ein anderer geht B -> A).

Wenn jedoch müssen Sie die notify nur anrufen, wenn erfolgreich den Wert transitioned könnten Sie so etwas wie dies versuchen:

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

Ich muss nur benachrichtigen, wenn geändert. Übrigens, verstehe ich gut, dass in meinem Fall, wenn Thread denselben Wert setzen möchte, ich Endlosschleife bekommen werde? – Edgar

+0

@ Edgar - nein. Ihre Schleife würde einfach funktionieren, wenn tmoPersistentState derselbe wie newPersistentState ist. Solange this.persistentState der gleiche wie tmpPersistentState ist, wird True und Breakout zurückgegeben. Es sollte keine Endlosschleife geben. – Madhusudhan

Verwandte Themen