程序员的自我修养(二)线程基础

线程

线程(又称轻量级进程)是程序执行流的最小单元。

一个标准的线程由线程id、当前指令指针、寄存器集合和堆栈组成。

一个进程由一个或多个线程组成,各线程之间共享程序的内存空间(包括代码段、数据段、堆等)及一些进程级资源(如打开文件和信号)。

  • 多线程可以互不干扰地并发地执行,并共享进程的全局变量和堆的数据。
线程私有 进程所有(线程之间共享)
局部变量、函数的参数、TLS数据 全局变量、堆上的数据、函数里的静态变量、程序代码、打开的文件

线程调度

线程通常拥有至少三种状态:

  • 运行:线程正在执行
  • 就绪:线程可以立刻执行,但CPU已经被占用
  • 等待:线程正在等待某一事件发生,无法执行。

程序员的自我修养(二)线程基础

线程调度算法:

  • 优先级调度
  • 轮转法

可抢占线程和不可抢占线程

Windows和Linux

Windows线程

CreateProcess
CreateThread

Linux任务

Linux将所有的执行实体都称为任务,每个任务概念上都类似于一个单线程的进程,具有内存空间、执行实体、文件资源等。
Linux下,不同的任务之间可以选择共内存空间–>共享了同一个内存空间的多个任务构成了一个“进程”,这些任务也就成了这个“进程”里的线程
fork : 复制当前进程
exec : 使用新的可执行映像覆盖当前可执行映像
clone : 创建子进程并从指定位置开始执行

写时复制
写时复制指的是,两个任务可以同时*地读取内存,但任意一个任务试图对内存进行修改时,内存会复制一份提供给修改方单独使用,以免影响到其他的任务使用。

线程安全

竞争与原子操作

WindowsAPI原子操作相关函数:
InterlockedExchange:原子地交换两个值
InterlockedDecrement:原子地减少一个值
InterlockedIncrement:原子地增加一个值
InterlockedXor:原子地进行异或操作

同步和锁
  • 信号量
  • 互斥量
  • 临界区
  • 读写锁
  • 条件变量
可重入与线程安全

一个函数被重写入,表示这个函数没有执行完成,由于外部因素或内部调用,又一次进入该函数执行。
一个函数要被重写入,可能的原因有:

  1. 多个线程同时执行这个函数
  2. 函数自身调用自身

一个函数被称为可重写入的,表明该函数被重写入之后不会产生任何不良后果。

可重入函数的特点:

  • 不使用任何(局部)静态或全局的非const变量
  • 不返回任何(局部)静态或全局的非const变量的指针
  • 仅依赖于调用方提供的参数
  • 不依赖任何单个资源的锁
  • 不调用任何不可重入的函数

线程模型

  • 一对一模型
  • 多对一模型
  • 多对多模型