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


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

    代码变序--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");
                }
            }
        }
  • 相关阅读:
    第一次留下自己的随笔
    NSOperation多线程方式
    NSThread多线程方式
    GCD多线程机制
    GCD创建单例常用的两种方法
    线程锁
    使用KVO模式,设置应用角标数字
    keyChain RSA加密 KVO
    NSURLConnection网络处理和NSURLSession网络处理
    UIAlertView和UIAlertViewController
  • 原文地址:https://www.cnblogs.com/lugesot/p/3571785.html
Copyright © 2020-2023  润新知