How should I increment a number for a round robin threading scenario with least contention?

c#, interlocked, multithreading

Solution

The trick is to do the operation in a loop until it is successful. I provide a general template for this approach in my answer here.

public int GetNextNumber()
{
  int initial, computed;
  do
  {
    initial = _lastNumber;
    computed = initial + 1;
    computed = computed > _maxNumbers ? computed = 1 : computed;
  } 
  while (Interlocked.CompareExchange(ref _lastNumber, computed, initial) != initial);
  return computed;
}

Problem

If many threads are calling `GetNextNumber` simultaneously with the following code, `GetNextNumber` will return 1 more times than any other numbers. ``` private class RoundRobbinNumber { private int _maxNumbers = 10; private int _lastNumber; private RoundRobbinNumber(int maxNumbers) { _maxNumbers = maxNumbers; } public int GetNextNumber() { int nextNumber = Interlocked.Increment(ref _lastNumber); if (_lastNumber > _maxNumbers) { Interlocked.CompareExchange(ref _lastNumber, 1, _maxNumbers); nextNumber = 1; } return nextNumber; } } ``` Is there a way to reset the `_lastNumber` back to one, and reliably return an incremented number for each thread calling `GetNextNumber()`, without having to use a lock?

Original source