0

只需找到一些關於非阻塞算法的信息,所以想要在實踐中使用它們。我將一些代碼從同步更改爲非阻塞,所以我想問一下我是否做得正確並保存了以前的功能。將同步方法轉換爲非阻塞算法

同步代碼:

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

我是否已經正確所做的一切,還是我錯過了一些東西:

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

我的非阻塞算法的選擇嗎?對代碼的任何建議和使用非阻塞方法來設置一般的abject?

+1

你不應該使用「this.persistentState.set(newPersistentState)」作爲compareAndSet更新persistentState的值 – hahn

+0

僅當將值設置爲newPersistentState並因此再次將其設置爲newPersistentState後,compareAndSet纔會從while循環中跳出,這不是必需的,正如hahn所述。如果需要,那麼這將是一個檢查後行爲的方式,這是容易出現陳舊的數據問題。謝天謝地,事實並非如此。 – Madhusudhan

回答

3

取決於你的意思是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(); 
    } 
} 
+0

我只需要在更改時通知。順便說一句,我理解很好,在我的情況下,如果線程將要設置相同的值,我會得到無限循環? – Edgar

+0

@Edgar - no。如果tmoPersistentState與newPersistentState相同,你的循環就可以正常工作。只要this.persistentState與tmpPersistentState相同,它將返回true和breakout。不應該有一個無限循環。 – Madhusudhan