zoukankan      html  css  js  c++  java
  • 实习总结:c#开发之旅(三)多线程小结(一)

          由于子系统中的任务,需要处理的数据量比较大,为了提高系统工作效率,老大要求使用多线程来执行任务,而我刚好负责流程控制这一块,当时真是被多线程折腾的死去活来,这个系统其实是有原型可以参考的,而且这个原型系统是久经考验,稳定性也很高;所以老大给我的时间并不多,我当时也没意识到难度会如此之大,但原型使用的是单线程,很多模块在单线程下跑得很欢,一到多线程就各种难了。

    其实现在想来,使用多线程并行处理数据,真心不算个好的决定。

    多线程适合处理的任务性质多为耗时的等待,或轮询判断状态。而此数据管理系统的瓶颈却是cpu运算和硬盘数据传输速度,后来测试结果也显示,多线程对性能的提升并不算太明显。当然这个不是主要原因,如果把系统布在强大的服务器上,性能提升还是有的。

    更主要的原因是:数据处理任务太不原子化了(额 不知道原子化的反义词是什么),线程安全程度非常低。详细说明下就是,任务执行的过程中,和太多其他模块有太多的交互了,而且大量使用了全局变量(比如处理任务需要的各种参数、配置、执行方案)和静态变量(数据库操作类的静态实例),一旦跑起多线程,就各种并发冲突。当时我又没有很清晰的意识到这个问题,于是到处加锁,在dal入口加锁,在任务存取数据的地方加锁,在使用DBHelper的静态对象地方加锁,搞得这部分异常复杂,而且加太多锁的后果就是性能进一步的下降,搞得几乎和单线程效率差不多了。

    额,说了半天废话,还没进入主题,有时间再接着整理(写)吧。


    (待续)

    这几天比较事多,今天有点功夫,接着写吧,

    其实让线程跑起来倒是不难,


     Thread thread1 = new Thread(delegate())

           {    //功能函数体               });

           thread1.Start();  这是匿名方法创建线程,当然,也可以先实例化delegate。一样的。

    也可以使用 ThreadPool.QueueUserWorkItem(DoDeleteInvoke)的方式。

    难就难在 thread的控制上,一般来说,如果要对线程执行的情况进行监控,控制,多使用前者。

    比如我需要根据用户设置,可以随时对线程进行挂起、恢复和销毁,基本就只能靠前者的方式了。

    最开始的时候,我是检查ThreadState然后使用Suspended和Resume方法,遇到了很多问题。

    //调用Resume方法可以恢复一个被延迟的线程。如果线程没有被延迟,Resume方法就是无效的。
    if (thread.ThreadState = ThreadState.Suspended){
      thread.Resume();
    }

    引用msdn:

    “只在少数几个调试方案中涉及线程状态枚举。您的代码在任何情况下都不应使用线程状态来同步线程的活动。”

    Thread .Suspend 和 Thread .Resume 方法通常并不是对所有应用程序都有用,并且不应将其与同步机制混淆。 由于 Thread .Suspend 和 Thread .Resume 不依赖于受控制线程的协作,因此,它们极具侵犯性并且会导致严重的应用程序问题,如死锁(例如,如果挂起的线程占有另一个线程需要的资源,就会发生这种情况)。”

    Thread有个threadState属性代表了线程的状态信息

    可以通过这个属性判断线程当时的状态,

    当一个thread实例刚创建时,他的threadstate是unstarted;当此线程被调用start()启动之后,他的threadstate是 running; 在此线程启动之后,如果想让他暂停(阻塞),能调用thread.sleep()方法,他有两个重载方法(sleep(int )、sleep(timespan)),只不过是表示时间量的格式不同而已,当在某线程内调用此函数时,他表示此线程将阻塞一段时间(时间是由传递给sleep 的毫秒数或timespan决定的,但若参数为0则表示挂起此线程以使其他线程能够执行,指定 infinite 以无限期阻塞线程),此时他的threadstate将变为waitsleepjoin,另外值得注意一点的是sleep()函数被定义为了static?! 这也意味着他不能和某个线程实例结合起来用,也即不存在类似于t1.sleep(10)的调用!正是如此,sleep()函数只能由需“sleep”的线程自己调用,不允许其他线程调用,正如when to sleep是个人私事不能由他人决定。不过当某线程处于waitsleepjoin状态而又不得不唤醒他时,可使用thread.interrupt方法 ,他将在线程上引发threadinterruptedexception。

    1, ms不推荐通过thread state这个属性来同步线程,msdn原话:

     重要事项

    只在几个调试方案中涉及线程状态。始终不应在代码中使用线程状态来同步线程活动。

    以前我就看到了这句话,但不太明白,今天的深入调试,才发现确实如此,必须要始终注意,cpu的时间片是不可控且不可预知的,所以你也不知道你现在线程的状态是不是一定如你预料,比如

    this._thread.ThreadState==ThreadState.running  很可能就不是你要的结果,可能线程的资源被抢占,现在处于watersleepjoin状态, 那么这句话返回的就是false了。


  • 相关阅读:
    第五周上机作业
    第四周练习
    第八周上机练习
    第七周作业
    第七周上机练习
    第六周作业
    第六周上机练习
    第五周上机作业
    第四周作业
    第四周上机练习
  • 原文地址:https://www.cnblogs.com/suijing/p/3379393.html
Copyright © 2011-2022 走看看