首页 > 编程语言 > 详细

多线程编程中的一个容易忽视的地方

时间:2015-11-17 10:33:59      阅读:277      评论:0      收藏:0      [点我收藏+]

 

前几天一直在查一个bug,在debug下程序在初始化的时候没有问题,release下程序在初始化的时候陷入了死循环,且挂载在vs上release又不会死循环,查了好久,昨天终于查到了为什么,这里暂时不提我自己做的项目,下面我写一个demo来说明这个问题:

程序如下:

 1 class Program
 2     {
 3         private static bool s_stop = false;
 4         static void Main(string[] args)
 5         {
 6             Console.WriteLine("Mian:letting worker run for 5 seconds");
 7             Thread t = new Thread(Worker);
 8             t.Start();
 9             Thread.Sleep(5000);
10             s_stop = true;
11             Console.WriteLine("Main:waiting for worker to stop");
12             t.Join();
13         }
14 
15         private static void Worker(object o)
16         {
17             Int32 x = 0;
18             while (!s_stop) x++;
19             Console.WriteLine("Worker:stopped when x={0}", x);
20         }
21     }

程序的目的是先让一个工作线程工作,5s后,给变量s_stop赋值,让线程的方法结束循环,程序最终会退出。

目的是好的,但是这个程序有个隐患,在debug下是没有问题的,挂调试器也是没有问题的,就是release模式下有问题,程序一直会陷入死循环。

为什么呢?

编译器会优化我们的代码,s_stop在主线程和工作线程中都要访问,这就会涉及到了数据共享问题,当编译器看到Worker方法的时候,发现里面的s_stop不会改变

,且这个值是false的,那么就把后面的代码都给优化了,因为whie(true)了。

 

这种错误,我们可能在编程过程中很难发现,也很难碰到,但是一旦碰到就是灾难。

我的项目中初始化的时候是这样子的:

console.Run();

while(!console.IsBusy){}

因为console.Run是一个线程,while()又是一个线程,但是一开始IsBusy是false的,所以在编译器优化的时候while就变成了死循环了。

 

最好的作法就是在变量前面加上Volatile关键字就可以了

 

http://files.cnblogs.com/files/monkeyZhong/TestVolatile.zip

 

多线程编程中的一个容易忽视的地方

原文:http://www.cnblogs.com/monkeyZhong/p/4970786.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!