2010-12-11 87 views
0

下面的演示代碼是如何線程安全的?我們正在確保CAS指令中的值是否未被修改,然後在int上進行增量。 return v + 1;步驟不會跳過整個目的,因爲它可以跳過線程的更新。使用compareAndSet進行線程安全

這裏原子整數用來模仿一個非阻塞int計數器。

//Here value is an atomic integer 
public int increment() 
{ 
    int v; 
    for(;;) 
    { 
     v = value.get(); 
     if(value.compareAndSet(v, v + 1)) 
     return v + 1; 
    } 
} 

不宜代碼是這樣的:

public int increment() 
{ 
    int v; 
    for(;;) 
    { 
     v = value.get(); 
     if(value.compareAndSet(v, v + 1)) 
     return value.get(); 
    } 
} 

回答

5

compareAndSet()返回true如果當前值等於預期值v,並且因此值更新爲v + 1

在你的第一個版本,如果兩個線程得到相同初始值,那麼一個會成功(更新到v + 1)和其他將失敗(因爲當前值不再v),並使用v + 1v + 2重試。

如果此代碼旨在返回唯一鍵,那麼第一個版本是正確的,因爲在compareAndSet()返回的點true當前值保證爲v + 1(即使只是短暫地)。如果另一個線程修改您撥打compareAndSet()get()的電話之間的值,第二個版本可能會因競爭狀態而返回重複值。這就是說,你可能想要調查AtomicIntegerincrementAndGet()方法,它幾乎是相同的事情,但更有效率(沒有顯式循環)。

2

定義的 「工作」。

假設value最初爲零。如果第一個函數被調用100次,它將返回1到100之間的每個數字,恰好一次。第二個函數沒有這個屬性。

這兩個函數都可以生成在函數返回時已過期的值。

哪個更「正確」的確取決於預期的語義increment