Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Returning number sequence in an optimised, thread safe manner

I'm looking for some advice on writing some thread safe, optimized, elegant code to do the following:

I want a static method to return a sequence of integers. So for example, the application starts, thread 1 calls the GetSequence method and says it wants to take 3, so it gets an integer array back consisting of 0,1,2. Thread 2 then calls the method and says give me 4, so it returns 3,4,5,6. Multiple threads can simultaneously call this method.

To give an idea of the sort of thing I'm thinking of, here's my attempt at this:

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

My questions therefore are: Am I approaching this in the best way, or is there another way to achieve this? Any suggestions for optimizing this code?

Many thanks in advance for any help.

like image 416
P2l Avatar asked Feb 21 '23 11:02

P2l


1 Answers

You probably want to look into the Interlocked class and it's Increment and Add methods:

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);
}
like image 92
Chris Shain Avatar answered Mar 15 '23 05:03

Chris Shain