如果有多个主题同时使用以下代码调用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()
的线程可靠地返回递增的数字,而不必使用锁?
答案 0 :(得分:4)
诀窍是在循环中执行操作,直到成功为止。我在答案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;
}
答案 1 :(得分:3)
不确定是否可以帮助除此之外的任何人更简单:
class RoundRobinNumber
{
private int _maxNumbers = 10;
private int _lastNumber = 0;
public RoundRobinNumber(int maxNumbers)
{
_maxNumbers = maxNumbers;
}
public int GetNextNumber()
{
int nextNumber = Interlocked.Increment(ref _lastNumber);
int result = nextNumber % _maxNumbers;
return result >= 0 ? result : -result;
}
}
答案 2 :(得分:1)
安德烈没有条件陈述的回答:
using System;
namespace Utils
{
public class RoundRobinCounter
{
private int _max;
private int _currentNumber = 0;
public RoundRobinCounter(int max)
{
_max = max;
}
public int GetNext()
{
uint nextNumber = unchecked((uint)System.Threading.Interlocked.Increment(ref _currentNumber));
int result = (int)(nextNumber % _max);
return result;
}
}
}
这是运行此代码的.net fiddle。