c# 并发编程系列之二:并发产生的问题

  在上一篇中介绍了进程、线程、线程池的概念后,本篇我们再进一步,看看并发产生时操作系统是如何执行的,

以及并发给编程带来哪些和传统编程不一样的问题。

 

一、并发(Concurrency)

    定义:同时做多件事情。

    解释:比如GUI程序中用户输入数据时同时对数据做处理;WEB服务器同时处理多个用户请求等。这里同时指

    的是一个时间区间,而不是一个时间点。

 

二、多线程(Multithreading)

    从操作系统的角度来说,多线程是一个时间段内有多个线程在运行,这多个线程可以属于同一个进程也可以属于

不同的进程。

    从编程的角度来说,多线程特指某个进程内有1个以上的线程在CPU上执行指令, 在这多个线程中,有一个是主线程,

其他的线程是由主线程创建的子线程,多线程是并发的微观表现形式。

 

三、多线程的2种运行情况

    ❒ 第一种:单核CPU

    CPU的执行是分时间片来进行的。

 

    在单核CPU的情况下,操作系统会分配一定的CPU时间片给线程去执行指令,线程在使用完时间片后被挂起,系统再将

CPU时间片分配给下一个线程,每个时间片依次轮流地执行各个应用程序的线程指令。由于一个时间片很短,相对于一个

应用程序来说,就好像是处理器在为自己单独服务一样,从而产生了多个应用程序在同时运行的效果。

 

    操作系统是如何分配CPU时间片给线程的呢?

    它是根据线程的优先级按一定的调度算法来对线程进行调度的。一般线程的优先级由两部分决定:自身在进程中的相对

优先级和所属进程的优先级。进程的调度算法有如下几种:

  ❐ 先来先服务 FCFS:First Come First Service

  ❐ 短作业优先/短进程优先 SJF / SPN:Shortest Job First / Shortest Process Next

  ❐ 高优先权优先 HPF:Highest Priority First

  高响应比优先 HRRN:Highest Response Ratio Next

  时间片轮转法 RR:Round-Robin

  多级反馈队列 MFQ:Multilevel Feedback Queue

 

    既然单核CPU在某个时间片内只能执行一个线程的指令,因此,要想我们的应用程序获得更快的执行速度,理论上应用程序

就应该开启多个线程来增加被CPU执行的次数。从而提高运行速度,这是我们进行多线程编程的出发点。

 

    【补充】: 实际情况不一定如此,即使优先级相同,考虑到线程的创建、切换、相互间的通讯、同步、回收等都是有时间

开销的,所以在单核CPU的情况下,如果没有I/O等耗时操作,应用程序使用多线程并不一定运行更快,这个要特别注意。

 

    单核CPU的结构如下图:

   

   

    第二种:多核CPU

    (1)多核CPU的产生

    CPU的主频越高运行越快,但是主频的增长也是有瓶颈的,在这种情况下,要获得更快的计算速度和更低的功耗,

芯片设计者开始绕过主频,转而在一块CPU中增加多个核心(Core),以此来提高CPU的算力 。

 

    (2)多核CPU的运行

    在多核CPU的情况下,一个CPU有多个处理核心(即多个逻辑处理器,如下图,笔者的电脑就有12个),操作系统可以

将多个线程分配到不同的逻辑处理器去运行,让线程的执行做到真正的并行(Parallel)。

   

   

    (3)多核CPU的调度

    多核CPU的任务调度算法有全局队列调度和局部队列调度。

 

    全局队列调度:操作系统维护一个全局的任务等待队列,当系统中有一个CPU核心空闲时,操作系统就从全局任务等待队列中

选取就绪任务开始在此核心上执行。这种算法的优点是CPU核心利用率较高。

 

    局部队列调度:操作系统为每个CPU内核维护一个局部的任务等待队列,当系统中有一个CPU内核空闲时,便从该核心的任务

等待队列中选取恰当的任务执行,这种方法的优点是任务基本上无需在多个CPU核心间切换,有利于提高CPU核心局部Cache命中率。

 

    目前多数多核CPU操作系统采用的是基于全局队列的任务调度算法。

   

    (4) 任务的2种类型

  ❒ 计算密集型

    要进行大量的计算,消耗CPU资源,比如数学计算、加密/解密等,因此任务数不宜过多;

  ❒ IO密集型

    CPU消耗很少,大部分时间都在等待IO操作完成,比如网络连接、文件读写等,因此任务越多,CPU效率越高;

 

    Inter(R) Core(TM) i5-4258 CPU示意图(双核四线程,3级缓存,L3多核心共享)

   

    CPU线程和操作系统线程是不一样的概念:

  ❐ 操作系统调度的基本单位是(软件的)线程;系统的线程数有几十上百个;

   CPU运算的基本单位是(硬件的)线程;CPU中一个核心一般只有2个线程,数量固定;

  ❐ 操作系统负责把它产生的(软)Thread 调度到CPU中的(硬)Thread 中去,最后由CPU的(硬)Thread 来执行。

 

四、并发带来的问题

    不管是单核CPU还是多核CPU,因为存在多个线程同时执行的情况,会产生下面的问题:

    ❐ 资源竞争

    ❐ 上下文切换

    ❐ 线程安全

    同步

    死锁

    并发编程就是在利用多线程好处的时候处理好它带来的种种问题。

 

posted @ 2021-06-06 00:27  屏风马  阅读(457)  评论(0编辑  收藏  举报