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


    前几天一直在查一个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

  • 相关阅读:
    django + scrapy 部署
    scrapyd 爬虫部署
    爬虫部署
    使用Scrapy爬取图片入库,并保存在本地
    学习Spider 了解 Scrapy的流程
    Django 的 一些基本操作:视图函数,路由配置
    Django 了解
    sql
    嚯嚯~ module 1
    Long Way To Go 之 Python 5 (2)
  • 原文地址:https://www.cnblogs.com/monkeyZhong/p/4970786.html
Copyright © 2020-2023  润新知