C# 多线程系列章节二:C#软件层面相关概念

下一章 会罗列这章所有的 知识点 以及一些 好的文章说明 去加深理解

多线程固然是好,因为高效所以才能流行。 钱当然挣得更多是好,但是 要想挣得多,得付出的也多才行!

所以说,想要利用多线程的好,就得下功夫去搞。足够了解,合理利用,就是关键。

什么场景使用/p>

既然是多线程,那多是关键,多个人不能打架不是,所以要在 独立任务的 情况下 多才好,就一个 面包 多个人吃 怕不是要吃出人命,得多个面包 多个人吃,各自吃各自的  那多好

什么场景不能使用/p>

在一个就是 查询数据库的时候,不能使用多线程,因为这是一个不可分割的任务。

总而言之,各个任务可以并发执行,各个任务可以分割,采用空间换时间的方式,就可以用多线程。

白话讲就是 一个人处理一桩事情,如果有另一个人来会捣乱  那就不能多线程,如果另一个人来 跟我没毛线关系,那就可以多线程。

要注意哪些弊端/p>

毕竟是 计算机 硬件 操控的 线程  都得听大哥的,大哥可不受咱程序控制,按照软件的心情。所以有这么以下特点 也算是 弊端

1.执行的无序性;尽量不要线程套线程

2.线程的不安全性;

3.捕获异常要在子线程调用的方法体里面 捕获;

 

具体分析特点弊端:

1 无序性 

因为之前说了  硬件是大哥,CPU 不管你软件思想  它只管 管理计算机 这么多的线程  分配时间 至于软件所想要的执行顺序  是不在乎的  同一个线程同一个计算 时间也不一定一样    知识点 CPU分片

任务来了 给时间   时间不够再给点  仅此而已 它不管 你这个任务是不是跟别的任务有关系

就像  老板在乎干的工作量多少,不在乎  谁先开始干的 张三9点5分 还是 李四9点6分,你只要是干完了相应工作量 就给你发钱就行了  你时间不够 再给你点时间 加班给我搞

 

2.不安全性

一:因为 无序性 是计算机大哥 的任性,但是 软件有顺序的概念,业务逻辑有顺序的概念    如果要保证顺序 怎么办嘞/p>

比如你  买衣服  买裤子  结账  三个独立的任务 看起来三个线程做没毛病,但是业务上你要最后付钱。这就有了顺序  不能衣服没买完 就结账了,这样 数据就有问题  也就不安全了

怎么办嘞/p>

最开始的方法就是  调用thred.join()  意思就是 别的线程等着我 结束才能  知识点:线程等待

后来发展有一个方法是线程池排序   知识点:线程池排序

二:多线程可能会对 同一个资源 进行操作   也就是所谓的竞争条件

比如多个线程,在同一时间,一个让一个小孩 往东,一个让一个小孩 往西,一个让一个小孩 往南,这小孩他不就懵逼了,我是谁 我在哪

怎么办嘞/p>

为了解决这个,出来一个概念叫线程同步  在同一时间只允许一个线程访问资源的情况称为线程同步   就是同一个时间 只会有一个线程 告诉这个小孩去哪

怎么实现嘞/p>

知识点 : 用户模式/内核模式  实现 线程同步     用户态 内核态  用户空间  内核空间   CPU切换上下文

运用锁(自旋锁/互斥锁/混合锁/读写锁) 无锁运算

1:内核模式    常见的做法使用锁lock  互斥锁,就是锁住这个资源不让别的线程动它    也就是 线程阻塞  让别的线程给我等着 候着不着急    锁的使用相当于让异步线程变同步 因为公用资源别的线程都不干活了 等着呢

但是这样做  其实是内核模式  也就是 切换了上下文 将别的线程 状态变成了 等待 阻塞      不去理会这些等待阻塞的线程 晾一会    去管理别的线程  这样就节省时间了

这适合等待时间比较长的操作,这样会减少大量的 CPU 时间损耗, 相对的 切换上下文 性能会 损耗

使用要注意点:锁只能锁一个引用类型,不能锁一个值类型,否则锁两个线程不能并发。
                         死锁:A线程锁了a B线程锁了b  A又需要用到b  B又需要用到a  这就相当于俩人面对面过独木桥 都得需要对方先过去才行

2:用户模式   短时间的  那就 不切换上下文  就等一会呗   浪费点CPU分片的时间,保留性能

实现手段其实就是 结合使用   混合模式  先用户模式 等 实在真是等的时间有点长了 那么就切换到 内核模式  线程阻塞一下 在阻塞状态以节省CPU资源。

原子操作 自旋锁

借助于Interlocked类,我们无需锁定任何对象即可获取到正确的结果。Interlocked提供了Increment, Decrement和Add等基本数学操作的原子方法,从而帮助我们,在编写Counter类时无需使用锁。

那可能会有疑问了,同一时间进入俩个线程  原子操作也还是有问题啊,这就需要了解 其实 从宏观来看  因为CPU执行太快 给一种 异步并发的唰唰唰的感觉,其实微观上 还是 单核CPU一次执行一个任务的

只不过这个间隔时间小到可以忽略罢了,所以 说原子操作 是可行的,毕竟存在那么一丢丢的间隔  还是有一个顺序的  原子操作 下一个任务就影响不了了

 

小结:CPU太快导致共享资源的问题   要不 原子操作 保证一下个任务哪怕特别紧随获取共享资源的时候 前一个任务也处理完了   要不就是锁住 处理完了再放开

          其实 锁住 处理  变相的就是将 锁住里面的处理  变成一个原子操作

3 异常机制

平常 捕获异常 直接 try catch 完事儿~

但是在线程内的异常,子线程会把异常吃掉,不会影响程序,你想啊 子线程在唰唰唰的执行,你主程序又不晓得,跟个憨批一样,你完犊子了都没人救你

所以要catch 子线程中的异常,try catch要加到内部,这样才能捕获到异常

4 知识点:线程池 线程调度

当线程多了之后 性能是一方面 (创建和回收线程资源)  管理起来也比较麻烦  为了更加合理化使用多线程   所以就出现 线程池

俩个人吃饭,一天吃三顿  没有必要6个碗   只需俩个碗 即可    线程池就是 根据资源情况 而启发式的 帮助我们管理线程 帮助我们创建和回收

 

 

 

 

 

 

来源:Marzlam

声明:本站部分文章及图片转载于互联网,内容版权归原作者所有,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2021年2月7日
下一篇 2021年2月7日

相关推荐