Reproduce torn reads of decimal in c#

放肆的年华 提交于 2019-12-20 03:54:17

问题


Seeing is believing. Can anyone reproduce a program that reads a torn decimal? I tried spinning up multiple threads changing the same decimal between 1 and 2. I did not catch any reads different from 1 or 2.

EDIT: I like to see that a reader thread does not see a atomic change from a writer thread, so the value should be something different from 1 or 2.

void TornDecimalReadTest()
    {
        decimal sharedDecimal = 1;
        int threadCount = 100;
        var threads = new List<Thread>();

        for (int i = 0; i < threadCount; i++)
        {
            int threadId = i;
            var thread = new Thread(() =>
            {
                Thread.Sleep(5000);

                decimal newValue = threadId % 2 == 0 ? 1 : 2;
                bool isWriterThread = threadId % 2 == 0;

                Console.WriteLine("Writer : " + isWriterThread + " - will set value " + newValue);

                for (int j = 0; j < 1000000; j++)
                {
                    if (isWriterThread)
                        sharedDecimal = newValue;

                    decimal decimalRead = sharedDecimal;

                    if (decimalRead != 1 && decimalRead != 2)
                        Console.WriteLine(decimalRead);
                }
            });

            threads.Add(thread);
        }

        threads.ForEach(x => x.Start());
        threads.ForEach(x => x.Join());
    }

回答1:


This code will demonstrate a torn read of a Decimal:

using System;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    class Program
    {
        void run()
        {
            Task.Run((Action) setter);
            Task.Run((Action) checker);

            Console.WriteLine("Press <ENTER> to stop");
            Console.ReadLine();
        }

        void setter()
        {
            while (true)
            {
                d = VALUE1;
                d = VALUE2;
            }
        }

        void checker()
        {
            for (int count = 0;; ++count)
            {
                var t = d;

                if (t != VALUE1 && t != VALUE2)
                    Console.WriteLine("Value is torn after {0} iterations: {1}", count, t);
            }
        }

        static void Main()
        {
            new Program().run();
        }

        Decimal d;

        const Decimal VALUE1 = 1m;
        const Decimal VALUE2 = 10000000000m;
    }
}

It happens faster in a release build than a debug build.

I think the reason that you weren't seeing a torn read in your test code is because you were only changing the value between 0 and 1. It's likely that the bits being changed during your test are all in the same word being used to store the value internally, and accesses to words are atomic.

By changing the value between 1 and 10000000000, we force bits to change in two different words, allowing a torn read to be observed.



来源:https://stackoverflow.com/questions/23262513/reproduce-torn-reads-of-decimal-in-c-sharp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!