pitchcontrol
11/25/2017 - 9:14 AM

Thread-safe-add

Потокобезопасное сложение

class Program
{
      
    private static double totalValue = 0;
        private static double AddToTotal(double addend)
        {
            double initialValue, computedValue;
            do
            {
                initialValue = totalValue;
                computedValue = initialValue + addend;
            }
            while (initialValue != Interlocked.CompareExchange(
                ref totalValue, computedValue, initialValue));
            return computedValue;
        }
        static void TestIncrement()
        {
            totalValue = 0;
            int length = 1000;
            int subLength = 1000;

            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            var tasks = new Task[length];
            for (int i = 0; i < length; i++)
            {
                var v = i;
                tasks[i] = Task.Factory.StartNew(() =>
                {
                    for (int j = 0; j < subLength; j++)
                    {
                        totalValue += 1;
                    }
                });
            }
            Task.WaitAll(tasks);
            stopwatch.Stop();
            Console.WriteLine($"Потоко не безопасное {totalValue}, {stopwatch.Elapsed}");

            tasks = new Task[length];
            totalValue = 0;

            Object lockObj = new object();
            for (int i = 0; i < length; i++)
            {
                var v = i;
                tasks[i] = Task.Factory.StartNew(() =>
                {
                    for (int j = 0; j < subLength; j++)
                    {
                        lock (lockObj)
                        {
                            totalValue += 1;
                        }
                    }
                });
            }
            Task.WaitAll(tasks);
            stopwatch.Stop();
            Console.WriteLine($"С использованием Lock {totalValue}, {stopwatch.Elapsed}");

            stopwatch.Restart();
            totalValue = 0;
            tasks = new Task[length];
            for (int i = 0; i < length; i++)
            {
                var v = i;
                tasks[i] = Task.Factory.StartNew(() =>
                {
                    for (int j = 0; j < subLength; j++)
                    {
                        AddToTotal(1);
                    }
                });
            }
            Task.WaitAll(tasks);
            stopwatch.Stop();
            Console.WriteLine($"С использованием Interlocked {totalValue}, {stopwatch.Elapsed}");
        }
}