C# 对于争用最少的循环线程方案,我应该如何增加一个数字?
如果许多线程同时调用以下代码C# 对于争用最少的循环线程方案,我应该如何增加一个数字?,c#,multithreading,interlocked,C#,Multithreading,Interlocked,如果许多线程同时调用以下代码GetNextNumber,GetNextNumber将比任何其他数字返回1次以上 private class RoundRobbinNumber { private int _maxNumbers = 10; private int _lastNumber; private RoundRobbinNumber(int maxNumbers) { _maxNumbers = maxNumbers; }
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;
}
}
有没有一种方法可以将
\u lastNumber
重置为1,并可靠地为调用GetNextNumber()
的每个线程返回递增的数字,而不必使用锁?诀窍是在循环中执行操作,直到成功为止。我在回答中提供了这种方法的通用模板
不确定是否有帮助,但这可能更简单:
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;
}
}
没有条件陈述的Andrey回答:
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;
}
}
}
这是一个运行此代码的方法。hmmm…在这里的msdn示例中使用了相同的方法:…但是,有一条评论说:“.NET Framework版本2.0中引入的Add方法提供了一种更方便的方法来累积线程安全整数的运行总数。”因此,我只是想确定我没有错过什么。谢谢你的意见。@EricDahlvang-你不是在要求一个总的。。。这很重要。这是一个聪明的解决方案,但我随时都喜欢lock()。@HenkHolterman:是的,我也是,但由于OP要求“最少争用”的解决方案,我认为它值得发布。@EricDahlvang:问题是
互锁。Add
不执行滚动逻辑。要正确设置值,您仍然需要在循环中输入一个。您还可以执行此操作返回(nextNumber<0?(nextNumber+int.MaxValue+1):nextNumber)%\u length
\u lastNumber
在Int32.MaxValue
调用@ChrisFulstow后最终将溢出,是,但互锁。增量将从int.MinValue开始(不会抛出)
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;
}
}
}