Ahmed Moheb
Ahmed Moheb

Reputation: 762

Ensure thread safety without lock statement in C#

I am trying to understand multi-threading and I have the following code and I need to ensure thread safety (typically without using lock statement) by getting the final result 10,000,000, but if you run the following code multiple time in VS you get different values close to 10,000,000 but never reaches it, so I need to fix this code without using lock statement.

using System;
using System.Threading;

namespace ConsoleApp1
{
    class Program
    {
        private static int _counter = 0;
        private static void DoCount()
        {
            for (int i = 0; i < 100000; i++)
            {
                _counter++;
            }
        }

        static void Main(string[] args)
        {
            int threadsCount = 100;
            Thread[] threads = new Thread[threadsCount];

            //Allocate threads
            for (int i = 0; i < threadsCount; i++)
                threads[i] = new Thread(DoCount);

            //Start threads
            for (int i = 0; i < threadsCount; i++)
                threads[i].Start();

            //Wait for threads to finish
            for (int i = 0; i < threadsCount; i++)
                threads[i].Join();

            //Print counter
            Console.WriteLine("Counter is: {0}", _counter);
            Console.ReadLine();
        }
    }
}

appreciate your help.

Upvotes: 1

Views: 1808

Answers (2)

Enigmativity
Enigmativity

Reputation: 117175

You're better off getting an understanding of threads, but then moving on quickly to a library that abstracts the complexity for you.

If you use Microsoft's Reactive Framework (aka Rx) - NuGet System.Reactive and add using System.Reactive.Linq; - then you can do this:

void Main()
{
    var query =
        from n in Observable.Range(0, 100)
        from x in Observable.Start(() => DoCount())
        select x;
        
    var counter = query.Sum().Wait();
        
    Console.WriteLine("Counter is: {0}", counter);
    Console.ReadLine();
}

private int DoCount()
{
    int counter = 0;
    for (int i = 0; i < 100000; i++)
    {
        counter++;
    }
    return counter;
}

Much easier and with the result: Counter is: 10000000

Upvotes: 1

Blindy
Blindy

Reputation: 67489

Yes, the Interlocked class of functions are the way to go for lock-free multi-threaded synchronization. In your specific case, you want Interlocked.Increment

Upvotes: 1

Related Questions