如果许多线程与以下代码同时调用GetNextNumber,则GetNextNumber返回的次数将比其他任何数字多1次。

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

有没有一种方法可以将_lastNumber重设为1,并为调用GetNextNumber()的每个线程可靠地返回递增的数字,而不必使用锁?

最佳答案

诀窍是循环执行操作,直到操作成功为止。我在回答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;
}

10-01 08:15