编程小技巧

    返回首页    发表留言
本文作者:李德强
          技巧二十:多线程原理
 
 

        今天跟大家分享的小技巧是关于多线程的。提到多线程很多人自然会想到如何在程序里创建一个多线程并执行它,它的生存周期是多久,如何对它做资源回收等等诸如此类的问题,但是我们今天所讲内容跟这些问题都没有太大关系。今天我们会以多线程为核心跟大家一起学习它的本质与原理,而不是讲如何使用这一机制。

        假设我们编写一个用于计算N以内的素数的程序,这个计算程序可以计算N以内的所有素数,任务写在我们的主函数main当中,我们称这样的功能位于程序的主线程当中。接下来我们需要对这个程序做一些修改,我们希望程序可以同时计算N以内的素数和M以内的素数,于是程序可以分为两个任务,任务A:计算N以内的素数;任务B计算M以内的素数。如果我们把这两个任务都编写在主函数main当中去,我们的程序则会这样执行:先计算N以内的素数,再计算M以内的素数。

        然而我们希望程序可以在运行时可以同时执行任务A和任务B,它们相互之间是“并行”的,相互之间不受影响,在执行任务A时无须等待任务B执行完成,而执行任务B时同样无须等待任务A执行完成。于是我们需要创建一个线程来负责执行任务B,而任务A原本在主线程中执行。

        不同的编程语言里创建多线程的方法大同小异,但原理是相同的,就是让一个程序可以同时执行多个任务。每个任务都有着自己独立的功能(但它们共享一个进程的资源)。在这里我们并不关心它们的具体实现,我们来分析一下多线程的执行原理。

        我们抛开CPU的多核多线程机制不管,来单独谈谈单核心单线程CPU是如何来处理多线程执行的,CPU在执行一个具有两个线程的程序任务时,通常是按时间片轮转的方式来分别执行两个任务(早期的操作系统都是按时间片轮转的方式来执行多任务的),执行一小段时间后,CPU将当前任务的状态临时保存,转去执行另一个任务,执行一小段时间后,再将这个任务的状态临时保存,再转回第一个任务继续执行。例如:任务A和任务B, CPU首先会载入这个线程的相关参数比如各个寄存器的内容、内存堆栈地址、执行代码位置等,并在应该执行代码处开始执行,当执行了一小段时间后将任务A的这些执行状态保存起来,转入任务B,载入任务B的相关参数比如各个寄存器的内容、内存堆栈地址、执行代码位置等,并在应该执行代码处开始执行,再过了一小段时间后将任务B的这些执行状态保存起来,再转到A任务,如此重复执行……

        当然,这个系统时间片是非常短的,当CPU在多个任务之间来回切换执行时,人们根本感觉不到这样的多个任务执行的停顿,所以当CPU执行多线程时,我们总是觉得多个任务在“同时执行”也就是“并行”,但其实从多线程的本质上来讲多个任务之间都是串行的,只不过在多任务切换时人们根本察觉不出来。

        现在个人电脑中的CPU通常是多核心多线程的,但是它们在执行时多线程数通常都没有系统中需要执行的程序的线程数多,甚至远远少于系统中需要执行的线程数,所以通常还是以多任务串行机制来实现“并行”的。上面例子中以时间片轮转的方式来讲述多线程的执行过程,但实际上操作系统有很多算法来计算每一个线程的执行优先级,并按最优的调度算法来执行它们。

        所以说,当我们写一个程序时如果想让其具有可完成多个任务的功能,就可以采用多线程机制来实现,但是多线程的本质是让多个任务“同时执行”,而从原理上说,它并不会从根本上加快整个程序的运行速度,也不会从根本上提高整个程序的执行效率。

 

        今天的小技巧你学会了吗?

 

    返回首页    返回顶部
#1楼  李德强  于 2017年08月28日16:44:47 发表
 
从原理上说,多线程并不会从根本上加快整个程序的运行速度,也不会从根本上提高整个程序的执行效率。

但是操作系统通常会根据其特有的优先级和算法来执行各个进程和线程,有时候使用多线程机制时可能会使任务执行更快一些,但本质在于操作系统的调度算法和进行的优先级设定,而并非是多线程机制使其运行速度提高了。
  看不清?点击刷新

 

  Copyright © 2015-2023 问渠网 辽ICP备15013245号