以优化的线程安全方式返回编号序列

本文关键字:返回 编号 方式 安全 优化 线程 | 更新日期: 2023-09-27 18:25:04

我正在寻找一些关于编写线程安全、优化、优雅的代码以完成以下任务的建议:

我想要一个静态方法来返回一个整数序列。例如,应用程序启动时,线程1调用GetSequence方法,并表示要取3,因此它得到一个由0,1,2组成的整数数组。然后线程2调用该方法并说给我4,所以它返回3,4,5,6。多个线程可以同时调用此方法。

为了了解我正在思考的事情,以下是我的尝试:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SequenceNumberService
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] numbers = NumberSequenceService.GetSequence(3);
            foreach (var item in numbers)
            {
                Console.WriteLine(item.ToString());
            }
            // Writes out:
            // 0
            // 1
            // 2
            Console.ReadLine();
        }
    }
    public static class NumberSequenceService
    {
        private static int m_LastNumber;
        private static object m_Lock = new Object();
        public static int[] GetSequence(int take)
        {
            int[] returnVal = new int[take];
            int lastNumber;
            // Increment the last audit number, based on the take value.
            // It is here where I am concerned that there is a threading issue, as multiple threads
            // may hit these lines of code at the same time.  Should I just put a lock around these two lines
            // of code, or is there a nicer way to achieve this.
            lock (m_Lock)
            {
                m_LastNumber = m_LastNumber + take;
                lastNumber = m_LastNumber;
            }
            for (int i = take; i > 0; i--)
            {
                returnVal[take - i] = lastNumber - i;
            }
            return returnVal;
        }
    }
}

因此,我的问题是:我是以最好的方式来解决这个问题,还是有其他方法来实现这个问题?有任何优化此代码的建议吗?

非常感谢您的帮助。

以优化的线程安全方式返回编号序列

您可能想了解Interlocked类及其Increment和Add方法:

public static Int32 num = 0;
public static Int32 GetSequence() 
{ 
    return Interlocked.Increment(ref num); 
}
public static IEnumerable<Int32> GetSequenceRange(Int32 count) 
{ 
    var newValue = Interlocked.Add(ref num, count);
    return Enumerable.Range(newValue - count, count);
}