如何使用无锁代码同步来自不同线程的添加?

时间:2012-07-05 13:43:53

标签: c#

我编写了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 += diff;

例如,如果一个线程执行nasdaqIndexValue += 10;而另一个线程执行nasdaqIndexValue += 3;,我需要确保添加完全正确的13。在这种情况下我是否需要同步?如果是这样,如何使用lock-free代码?

UPD oooops我刚刚意识到使用这样的代码我每次都会向nasdaqIndex引入小“delta”,如果我使用的是双打。所以我要么使用小数,要么我必须“完全重新计算”纳斯达克指数,否则它不会等于一段时间后的股票总和。

2 个答案:

答案 0 :(得分:1)

使用Interlocked类型将该操作设为原子操作:

Interlocked.Add(ref nasdaqIndexValue, diff);

答案 1 :(得分:1)

使用volatile关键字。

  

volatile修饰符通常用于访问的字段   多个线程,不使用lock语句来序列化访问。

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