0

I've wrote simple example of NasdaqIndex calculation. For simplicity I declared it as int and this is just sum of prices of 10 stocks.

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!
}

}

But in real life StockValueUpdated may (and will) be called parallel from different threads for different stockValueIndex (it will not be called parallel for the same stockValueIndex).

So I just have to synchronize only one line of code nasdaqIndexValue += diff;

For example if one thread executes nasdaqIndexValue += 10; and another thread executed nasdaqIndexValue += 3; I need to be sure that tottally exactly 13 is added. Do I need synchronization in this case at all? If so how to do that using lock-free code?

UPD oooops I just realized that using such code I introduce small "delta" to nasdaqIndex every time if I'm using doubles. So I have either use decimal or I have to "recalculate completely" nasdaqIndex sometimes, otherwise it will not be equal to sum of stocks after a while.

Oleg Vazhnev
  • 23,239
  • 54
  • 171
  • 305
  • Integer operations are atomic, but I'm not sure how far that goes... – Ry- Jul 05 '12 at 13:48
  • Why does it need to be lock free? – Katie Kilian Jul 05 '12 at 13:49
  • @CharlieKilian because it would be faster – Oleg Vazhnev Jul 05 '12 at 13:49
  • @minitech but we have 2 integer operation `a = a + b` is not atomic operation I guess – Oleg Vazhnev Jul 05 '12 at 13:50
  • 1
    @javapowered: That's what I'm finding out; I don't know if that would be optimized to an atomic operation. Or maybe I'm just confused this morning and it obviously won't work :) Anyway, your "synchronized" and "lock-free" requirements are incompatible. – Ry- Jul 05 '12 at 13:53
  • @javapowered Are you completely sure the `lock` would slow it down to the point that using one is unfeasible? I'm thinking of the guideline that you shouldn't optimize before you've profiled... – Katie Kilian Jul 05 '12 at 13:53
  • 1
    @CharlieKilian yes I profilied, i was using `BlockingCollection` and that introduce `18 mcs` delay, while with `lockfree` code I only have `2 mcs` delay. – Oleg Vazhnev Jul 05 '12 at 13:55

2 Answers2

1

Use Interlocked type to make that operation as atomic:

Interlocked.Add(ref nasdaqIndexValue, diff);
Sergei B.
  • 3,227
  • 19
  • 18
1

Use the volatile keyword.

The volatile modifier is usually used for a field that is accessed by multiple threads without using the lock statement to serialize access.

private volatile int nasdaqIndexValue; // for simplicity let's assume that already initialized
Ry-
  • 218,210
  • 55
  • 464
  • 476
Jim
  • 4,910
  • 4
  • 32
  • 50
  • i'm not sure if this will help. `Interlocked.Add` sounds exactly as what I need – Oleg Vazhnev Jul 05 '12 at 14:06
  • Interlocked will work but so will volatile. I like volatile because it doesn't "interfere" with the readability of the code. – Jim Jul 05 '12 at 14:24
  • I didn't see you were using this with double/decimal in your real world scenario, so yeah volatile won't work with that. – Jim Jul 05 '12 at 14:35