2012-07-05 55 views
0

我已經寫了NasdaqIndex計算的簡單例子。爲簡單起見,我宣佈它爲int,這只是10股票價格的總和。如何使用無鎖代碼同步來自不同線程的添加?

class NasdaqIndex { 

private int[] stockValue = new int[10]; // for simplicity let's assume they are already initialized 

// just sum from 1 to 10 of stockValue 
private int nasdaqIndexValue; // for simplicity let's assume that already initialized 

public void StockValueUpdated(int stockValueIndex, int newValue) { 
    int diff = newValue - stockValue[stockValueIndex]; 
    stockValue[stockValueIndex] = newValue; 
    nasdaqIndexValue += diff;    // THIS NEED TO BE SYNCHRONIZED! 
} 

} 

但在現實生活StockValueUpdated可能(並且會)被從不同stockValueIndex不同的線程(它不會被調用同一stockValueIndex平行)稱爲並行。

所以我只是如果一個線程執行nasdaqIndexValue += 10;同步只有一行代碼nasdaqIndexValue += diff;

例如,而另一個線程執行nasdaqIndexValue += 3;我需要確保tottally正是13加入。在這種情況下,我需要同步嗎?如果是這樣,使用lock-free代碼怎麼辦?

UPD oooops我剛剛意識到,使用這樣的代碼,我會每次引入小的「delta」到nasdaqIndex,如果我使用雙打的話。因此,我要麼使用小數,要麼有時需要「完全重新計算」納斯達克指數,否則在一段時間後它不會等於股票的總和。

+0

整數運算是原子,但我不知道多遠是去... – Ryan 2012-07-05 13:48:28

+0

爲什麼它必須是無鎖? – 2012-07-05 13:49:31

+0

@CharlieKilian因爲它會更快 – javapowered 2012-07-05 13:49:50

回答

1

使用Interlocked類型,使該操作爲原子:

Interlocked.Add(ref nasdaqIndexValue, diff); 
+0

這是'++',而不是'+ = diff'。 – Ryan 2012-07-05 13:53:40

+0

是的,我的錯,thx! – 2012-07-05 13:54:25

+0

已更新我的回答 – 2012-07-05 13:55:55

1

使用volatile關鍵字。

volatile修飾符通常用於多個線程訪問的字段,而不使用lock語句來序列化訪問。

private volatile int nasdaqIndexValue; // for simplicity let's assume that already initialized 
+0

我不知道如果這將有所幫助。 'Interlocked.Add'完全聽起來像我所需要的 – javapowered 2012-07-05 14:06:12

+0

聯鎖可以工作,但會變得不穩定。我喜歡易變,因爲它不會干擾代碼的可讀性。 – Jim 2012-07-05 14:24:39

+0

我沒有看到你在真實世界的場景中使用了雙精度/十進制,所以是易變的將不起作用。 – Jim 2012-07-05 14:35:57