线程
线程简介
一个程序只有一个执行点(一个程序计数器,用来存放要执行的指令),但多线程(multi-threaded)程序会有多个执行点(多个程序计数器,每个都用于取指令和执行)。
换一个角度来看,每个线程类似于独立的进程,只有一点区别:它们共享地址空间,从而能够访问相同的数据。
单个线程的状态与进程状态非常类似。线程有一个程序计数器(PC),记录程序从哪里获取指令。每个线程有自己的一组用于计算的寄存器。
如果有两个线程运行在一个处理器上,从运行一个线程(T1)切换到另一个线程(T2)时,必定发生上下文切换(context switch)。线程之间的上下文切换类似于进程间的上下文切换。对于进程,我们将状态保存到进程控制块(Process Control Block,PCB)。现在,我们需要一个或多个线程控制块(Thread Control Block,TCB),保存每个线程的状态。但是,与进程相比,线程之间的上下文切换有一点主要区别:地址空间保持不变(即不需要切换当前使用的页表)。
在多线程的进程中,每个线程独立运行,当然可以调用各种例程来完成正在执行的任何工作。不是地址空间中只有一个栈,而是每个线程都有一个栈。
线程共享资源 | 线程独享资源 |
---|---|
地址空间 | 程序计数器 |
全局变量 | 寄存器 |
打开的文件 | 栈 |
子进程 | 状态字 |
信号及信号服务程序 |
线程 API
线程创建
|
|
该函数有 4 个参数:thread、attr、start_routine 和 arg。
- 第一个参数 thread 是指向 pthread_t 结构类型的指针,我们将利用这个结构与该线程交互,因此需要将它传入 pthread_create(),以便将它初始化。
- 第二个参数 attr 用于指定该线程可能具有的任何属性。一些例子包括设置栈大小,或关于该线程调度优先级的信息。
- 第三个参数最复杂,但它实际上只是问:这个线程应该在哪个函数中运行?在 C 中,我们把它称为一个函数指针(function pointer),这个指针告诉我们需要以下内容:一个函数名称(start_routine)。
- 第四个参数 arg 就是要传递给线程开始执行的函数的参数。
线程完成
|
|
该函数有两个参数。
- 第一个是 pthread_t 类型,用于指定要等待的线程。
- 第二个参数是一个指针,指向你希望得到的返回值。因为函数可以返回任何东西,所以它被定义为返回一个指向 void 的指针。
锁
|
|
条件变量
|
|
线程的生命周期
|
|
创建:一个新的线程被创建,等待该线程被调用执行; 就绪:时间片已用完,此线程被强制暂停,等待下一个属于它的时间片到来; 运行:此线程正在执行,正在占用时间片; 阻塞:也叫等待状态,等待某一事件(如 IO 或另一个线程)执行完; 退出:一个线程完成任务或者其他终止条件发生,该线程终止进入退出状态,退出状态释放该线程所分配的资源。
线程通信
线程间的通信目的主要是用于线程同步,所以线程没有像进程通信中的用于数据交换的通信机制。
互斥锁
互斥锁是最常见的线程同步方式,它是一种特殊的变量,它有 lock 和 unlock 两种状态,一旦获取,就会上锁,且只能由该线程解锁,期间,其他线程无法获取。
优点:使用简单;
缺点:
- 重复锁定和解锁,每次都会检查共享数据结构,浪费时间和资源;
- 繁忙查询的效率非常低;
条件变量
条件变量的方法是,当线程在等待某些满足条件时使线程进入睡眠状态,一旦条件满足,就唤醒,这样不会占用宝贵的互斥对象锁,实现高效。
条件变量允许线程阻塞并等待另一个线程发送信号,一般和互斥锁一起使用。
条件变量被用来阻塞一个线程,当条件不满足时,线程会解开互斥锁,并等待条件发生变化。一旦其他线程改变了条件变量,将通知相应的阻塞线程,这些线程重新锁定互斥锁,然后执行后续代码,最后再解开互斥锁。
读写锁
读写锁 也称之为 共享-独占锁,一般用在读和写的次数有很大不同的场合。即对某些资源的访问会出现两种情况,一种是访问的排他性,需要独占,称之为写操作;还有就是访问可以共享,称之为读操作。
适用场景:读写锁最适用于对数据结构的读操作次数多于写操作次数的场合。
信号量
信号量 和互斥锁的区别在于:互斥锁只允许一个线程进入临界区,信号量允许多个线程同时进入临界区
可以这样理解,互斥锁使用对同一个资源的互斥的方式达到线程同步的目的,信号量可以同步多个资源以达到线程同步。
信号
类似进程间的信号处理
死锁
死锁的四个必要条件
- 资源互斥
- 持有并等待
- 不能抢占
- 循环等待
死锁的应对方法
- 顺其自然,不予理睬
- 死锁检测与修复
- 死锁的动态避免
- 死锁的静态防止
- 清除四个必要条件中的一个
- 资源共享
- 一次性抢到所有锁
- 允许抢占资源
- 顺序请求资源
参考
《操作系统之哲学原理第 2 版》邹恒明
《操作系统导论》