C# 多线程的坑 之 代码变序
英文好的,可跳过,直接打开底部的“参考“链接。
代码变序--reordering of memory operations
大概4年前,阅读了这篇文章后http://www.albahari.com/threading/,我就自我满足,多线程编程不过就是用那些工具而已。
今天,读了一篇文章后,http://msdn.microsoft.com/en-us/magazine/jj863136.aspx,才发现C#代码是可以变序的(上面的文章也提到了,忘得一干二净)。
举例,你写出如下的代码
- void Init() {
- _data = 42;
- _initialized = true;
- }
JIL运行时的代码却可以像这样(不是IL代码哦,IL编译出代码与源代码是一致的)
- void Init() {
- _initialized = true;
- _data = 42;
- }
这个坑爹的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# 多线程的坑 之 代码变序的更多相关文章
- 多线程爬坑之路-Thread和Runable源码解析之基本方法的运用实例
前面的文章:多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类) 多线程爬坑之路-Thread和Runable源码解析 前面 ...
- [LeetCode系列] 变序词查找问题(Anagrams)
给定一系列词, 找出其中所有的变序词组合. Note: 变序词 - 组成字符完全相同但次序不同的单词. 如dog和god, ate和eat. 算法描述: 使用map<string, vector ...
- STL学习笔记(变序性算法)
变序性算法改变元素的次序,但不改变元素值. 这些算法不能用于关联式容器,因为在关联式容器中,元素有一定的次序,不能随意变动. 逆转元素次序 void reverse(BidirectionalIter ...
- 用AOP来让你的JS代码变得更有可维护性吧
此文已由作者吴佳祥授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 好吧我承认这是篇任务. 最近看到个消息,ES2017已经定稿了,心想,我去,还完全没了解ES2016呢,ES ...
- 【如何让代码变“高级”(二)】-这样操作值得一波666(Java Stream)(这么有趣)
[如何让代码变“高级”(二)]-这样操作值得一波666(Java Stream)(这么有趣) 开发中的代码 在开发中的代码是不是很常见这样的代码: 这样的? for循环取元素取值 List<Us ...
- java 多线程: Thread 并发访问-代码块同步synchronized {};String作为被锁的对象
方法同步的弊端 方法同步的时候,如果一个方法需要线程安全控制的代码速度其实很快,但是还有其他的业务逻辑代码耗时非常长(比如网络请求),这样所有的线程就在这一块就等待着了,这样造成了极大的资源浪费如果并 ...
- 多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类)
前言:刚学习了一段机器学习,最近需要重构一个java项目,又赶过来看java.大多是线程代码,没办法,那时候总觉得多线程是个很难的部分很少用到,所以一直没下决定去啃,那些年留下的坑,总是得自己跳进去填 ...
- css 填坑常用代码分享
以下是常用的代码收集,没有任何技术含量,只是填坑的积累.转载请注明出处,谢谢. 因为提交比较麻烦,后来转置github:https://github.com/jsfront/src/blob/mast ...
- 多线程爬坑之路-ThreadLocal源码及原理的深入分析
ThreadLocal<T>类:以空间换时间提供一种多线程更快捷访问变量的方式.这种方式不存在竞争,所以也不存在并发的安全性问题. This class provides thread-l ...
随机推荐
- K贪心
<span style="color:#330099;">/* K - 贪心 基础 Time Limit:1000MS Memory Limit:32768KB 64b ...
- MongoDB学习笔记06
在shell中删除一个集合,执行db.test.drop()或者db.runCommand({"drop":"test"}),在MongoDB中命令其实是作为一 ...
- SQL日期形式转换
在SQL Server中,有时存储在数据库中的日期格式和我们需要显示在页面上的格式不相同,我们需要转化成需要的格式. 特在此总结了一下常用的日期格式. --当前时间 SELECT GETDATE(); ...
- emjio表情转json
今天碰到了上传文字给服务端的时候emjio表情转成json就不对了 有大神帮忙解决了,记笔记记笔记--- #import "NSString+EncodedString.h" @i ...
- Unity-视图操作
按下 F 键使画面的视角移动到被选中对象的正面 视图场景摄像机(14年的时候,这个操作弄的头晕--) 旋转:Alt(Command)+左键拖拽 平移:Alt+Ctrl(Command)+左键拖拽 旋转 ...
- C语言enum再学习
通常来说我们使用enum是这样的: enum week{ Mon, Tue, ... Sun }; enum week w; w = Mon; 这里默认Mon~Sun的值为0~6 也可以自己定值 , ...
- NYOJ 45 棋盘覆盖
棋盘覆盖 水题,题不难,找公式难 import java.math.BigInteger; import java.util.Scanner; public class Main { public s ...
- 在word中使用notepad++实现代码的语法高亮
转载自:http://blog.csdn.net/woohello/article/details/7621651 有时写文档时需要将代码粘贴到word中,但直接粘贴到word中的代码虽能保持换行与缩 ...
- InetAddress类的使用
1.1. 简介 IP地址是IP使用的32位(IPv4)或者128位(IPv6)位无符号数字,它是传输层协议TCP,UDP的基础.InetAddress是Java对IP地址的封装,在java.net中有 ...
- java.lang.ClassNotFoundException: org.apache.struts.action.ActionServlet