·您现在的位置: 云翼网络 >> 文章中心 >> 网站建设 >> 网站建设开发 >> ASP.NET网站开发 >> C#多线程的坑之代码变序

C#多线程的坑之代码变序

作者:佚名      ASP.NET网站开发编辑:admin      更新时间:2022-07-23

英文好的,可跳过,直接打开底部的“参考“链接。

 

代码变序--reordering of memory Operations

大概4年前,阅读了这篇文章后http://www.albahari.com/threading/,我就自我满足,多线程编程不过就是用那些工具而已。

今天,读了一篇文章后,http://msdn.microsoft.com/en-us/magazine/jj863136.aspx,才发现C#代码是可以变序的(上面的文章也提到了,忘得一干二净)。

举例,你写出如下的代码

  1. void Init() {
  2.   _data = 42;
  3.   _initialized = true;
  4. }

JIL运行时的代码却可以像这样(不是IL代码哦,IL编译出代码与源代码是一致的)

  1. void Init() {
  2.   _initialized = true;
  3.   _data = 42;
  4. }

这个坑爹的JIL优化,如果不注意,可能就不会抓住bug所在。底部有我写的再现方法。先别运行程序,试试猜猜结果有几种可能。

 

 

总结:浮躁+记忆力差是很致命的,必须要找适合自己的工作方式。深入理论上理解+上手验证,这样才算消化,也不容易忘。

不重复造轮子,更不能重复学习。

参考:

http://msdn.microsoft.com/en-us/magazine/jj863136.aspx

http://msdn.microsoft.com/en-us/magazine/jj883956.aspx

    class PRogram
    {
        static void Main(string[] args)
        {
            DataInit di = new DataInit();
            new Thread(() => { di.Init(); }) { IsBackground = true }.Start();
            new Thread(() => { di.Print(); }) { IsBackground = true }.Start();

            Console.WriteLine("Running... Press enter to quit");
            Console.ReadLine();
        }
    }


    public class DataInit
    {
        private int _data = 0;
        private bool _initialized = false;
        //准备些无用的field
            private char _c = '0';
            private int _data1 = 0;
            private int _data2 = 0;
            private int _data3 = 0;
            private int _data4 = 0;

        public void Init()
        {
            _data = 42;            // Write 1
            _initialized = true;   // Write 2
            //下面的field赋值是用来触发JIL 优化的,如何触发的原理,我不知道:(。
            ///*try屏蔽下面的代码,结果很可能就是42了
                _c = '0';
                _data1 = 0;
                _data = 0;
                _data2 = 0;
                _data3 = 0;
                _data4 = 0;
        }
        public void Print()
        {
            Console.WriteLine(_data);   
            Console.WriteLine(_initialized); 

            if (_initialized)
            {
                Console.WriteLine(_data); //should 42,有时候确是0
            }
            else
            {
                Console.WriteLine("Not initialized");
            }
        }
    }