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

代码变序--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 = ;
private bool _initialized = false;
//准备些无用的field
private char _c = '';
private int _data1 = ;
private int _data2 = ;
private int _data3 = ;
private int _data4 = ; public void Init()
{
_data = ; // Write 1
_initialized = true; // Write 2
//下面的field赋值是用来触发JIL 优化的,如何触发的原理,我不知道:(。
///*try屏蔽下面的代码,结果很可能就是42了
_c = '';
_data1 = ;
_data = ;
_data2 = ;
_data3 = ;
_data4 = ;
}
public void Print()
{
Console.WriteLine(_data);
Console.WriteLine(_initialized); if (_initialized)
{
Console.WriteLine(_data); //should 42,有时候确是0
}
else
{
Console.WriteLine("Not initialized");
}
}
}

C# 多线程的坑 之 代码变序的更多相关文章

  1. 多线程爬坑之路-Thread和Runable源码解析之基本方法的运用实例

    前面的文章:多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类) 多线程爬坑之路-Thread和Runable源码解析 前面 ...

  2. [LeetCode系列] 变序词查找问题(Anagrams)

    给定一系列词, 找出其中所有的变序词组合. Note: 变序词 - 组成字符完全相同但次序不同的单词. 如dog和god, ate和eat. 算法描述: 使用map<string, vector ...

  3. STL学习笔记(变序性算法)

    变序性算法改变元素的次序,但不改变元素值. 这些算法不能用于关联式容器,因为在关联式容器中,元素有一定的次序,不能随意变动. 逆转元素次序 void reverse(BidirectionalIter ...

  4. 用AOP来让你的JS代码变得更有可维护性吧

    此文已由作者吴佳祥授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 好吧我承认这是篇任务. 最近看到个消息,ES2017已经定稿了,心想,我去,还完全没了解ES2016呢,ES ...

  5. 【如何让代码变“高级”(二)】-这样操作值得一波666(Java Stream)(这么有趣)

    [如何让代码变“高级”(二)]-这样操作值得一波666(Java Stream)(这么有趣) 开发中的代码 在开发中的代码是不是很常见这样的代码: 这样的? for循环取元素取值 List<Us ...

  6. java 多线程: Thread 并发访问-代码块同步synchronized {};String作为被锁的对象

    方法同步的弊端 方法同步的时候,如果一个方法需要线程安全控制的代码速度其实很快,但是还有其他的业务逻辑代码耗时非常长(比如网络请求),这样所有的线程就在这一块就等待着了,这样造成了极大的资源浪费如果并 ...

  7. 多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类)

    前言:刚学习了一段机器学习,最近需要重构一个java项目,又赶过来看java.大多是线程代码,没办法,那时候总觉得多线程是个很难的部分很少用到,所以一直没下决定去啃,那些年留下的坑,总是得自己跳进去填 ...

  8. css 填坑常用代码分享

    以下是常用的代码收集,没有任何技术含量,只是填坑的积累.转载请注明出处,谢谢. 因为提交比较麻烦,后来转置github:https://github.com/jsfront/src/blob/mast ...

  9. 多线程爬坑之路-ThreadLocal源码及原理的深入分析

    ThreadLocal<T>类:以空间换时间提供一种多线程更快捷访问变量的方式.这种方式不存在竞争,所以也不存在并发的安全性问题. This class provides thread-l ...

随机推荐

  1. DataList、Repeater、GridView中的Checkbox取值问题

    先看页面代码 <asp:DataList id="DataList1" runat="server" Width="100%" Rep ...

  2. 学习使用Vim(二)——User Manuals, Getting Started

    Vim的用户手册主要包含以下三个部分:     Getting Started;     Editing Effectively;     Tuning Vim;     分别代表基本编辑技巧,更优化 ...

  3. PHP学习笔记十八【构造函数】

    <?php class Person{ public $name; public $age; //定义构造函数 function 空格__construct 构造方法没有返回值,对象自动调用 p ...

  4. Android网络连接的两种方法:apache client和httpurlconnection的比较

    另见http://blog.csdn.net/mingli198611/article/details/8766585 在官方blog中,android工程师谈到了如何去选择apache client ...

  5. [汇编语言]-第十章 ret,retf,call指令

    1- ret 相当于 pop IP;用栈中数据,修改IP内容.从而实现近转移. 执行后(IP)=0, CS:IP指向代码段的第一条指令. assume cs:code stack segment db ...

  6. python笔记之subprocess模块

    python笔记之subprocess模块 [TOC] 从Python 2.4开始,Python引入subprocess模块来管理子进程,以取代一些旧模块的方法:如 os.system.os.spaw ...

  7. html css 笔记

    cursor其他取值 鼠标移入    auto          :标准光标    default        :标准箭头    pointer        :手形光标    wait       ...

  8. jQuery中$符号冲突问题 (转载)

    Jquery的$命名冲突: 在Jquery中,$是JQuery的别名,所有使用$的地方也都可以使用JQuery来替换,如$('#msg')等同于JQuery('#msg') 的写法.然而,当我们引入多 ...

  9. leiningen安装记录

    Leiningen是Clojure项目管理工具Leiningen is the easiest way to use Clojure,官网:http://leiningen.org/ 1:首先下载Le ...

  10. Qt带来的是更加低廉的开发成本和学习成本,对于很多小公司而言,这种优势足以让他们获得更大的利润空间 good

    不能单纯从技术上来看待这个问题,Qt本来是小众的开发平台,个人认为,它的出现只是解决特性场景的特定问题,Qt带来的是更加低廉的开发成本和学习成本,对于很多小公司而言,这种优势足以让他们获得更大的利润空 ...