• 多线程编程总结:一、认识多线程本质


           在当今计算机系统中,已经大量存在多核心CPU,或者是在多核心基础上有进一步的超线程技术将虚拟CPU数量翻倍。在计算机发展之初,我们的应用程序是按照一个CPU只做一件事情来应用,也就是顺序执行。随着时间的不断变化,我们的CPU计算能力越加强大,那么我们可以使用线程技术,让每个核心都去做一件事,或者使用时间切片(time slicing)技术,让我们的CPU在各个线程中切换以同时达到一种处理多个线程任务的目标。可以同时听歌,看文档,运行时钟,挂游戏。

           需要注意的是,对于时间分片技术,我们实际上是同一个核心将一个线程的运行1个时间片(time slice)的时间,然后保存状态,切换到另外一个线程去,这种切换动作被称为上下文切换。表现出来是并行运算。但是我们需要考虑到CPU不断地切换线程,实际上也会有代价,需要保存上一个线程状态,切换到下一个线程去。如果线程数目过多的情况下,就会消耗大量时间在切换线程上。这就是为什么多线程不一定会让程序更快,而需要综合衡量。

           多线程并发问题:缺乏原子性、竞态条件、复杂的内存模型和死锁。

    一、缺乏原子性

           首先原子操作的定义是:一个原子内代码,要么处于没有操作,要么已经操作完毕,而不存在“操作中”这个中间态。核心是它是整体的,不可分割。如果我们的多线程代码如果不是原子性的,那么这种情况下它就缺乏原子性。

    二、竞态条件

           竞态条件是值得我们同时开启的多个线程,它的执行顺序是根据系统判断哪个线程竞争胜利,先执行到一部分,然后发生上下文切换到另外一个另外一个线程去。而至于哪个线程在竞争中胜出不可预知,就算99.99%的时间具有正确行为,那么也有0.01%会出现另外一个线程竞争胜利。

    三、复杂的内存模型

          现在我们的CPU不会每次运行某个变量的时候都会去内存取出操作,而是将这个变量缓存在CPU的高速缓存中,这个缓存会定时和主内存进行同步。意味着在多核心CPU中处理不同线程时,我们的线程处理的是各自CPU核心的高速缓存中的变量,实际上是2个不同的变量。那么当我们多线程对该变量进行更新时就不是准确的。

    四、锁定造成死锁

           C#中使用Lock语句或者Monitor.Enter() Monitor.Exit()将一段代码作为原子操作,对Lock住的该对象,系统会判断只允许一个线程访问该段Lock住代码,其他线程挂起等待。如果被Lock住的对象发生改变,其他线程访问过来的时候,系统会认为不是同一段Lock代码,就会允许那个代码访问,这就是Lock失效了。 

            锁本身也会出问题,例如此处有2个线程分别是A和B线程, 同时有2个锁分别是C和D,那么A线程在C锁获得之后请求D锁,而B线程在获得D锁之后请求C锁,就会造成互相等待对方释放,这就是死锁的由来。

  • 相关阅读:
    SQL Server 使用全文索引进行页面搜索
    基于TI Davinci架构的多核/双核开发高速扫盲(以OMAP L138为例),dm8168多核开发參考以及达芬奇系列资料user guide整理
    HBase 数据库检索性能优化策略
    在oracle存储过程中创建暂时表
    永和维护---从问题中得到的一些感受
    spring set注入
    为计算机教育改革而摇旗呐喊
    hdu5288 OO’s Sequence 二分 多校联合第一场
    HTML5贪吃蛇源代码
    软工初体验
  • 原文地址:https://www.cnblogs.com/chengxingliang/p/14790267.html
Copyright © 2020-2023  润新知