Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 对于争用最少的循环线程方案,我应该如何增加一个数字?_C#_Multithreading_Interlocked - Fatal编程技术网

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