1. 从进程到线程
体验了上一篇的爬楼模拟程序后,相信你能稍微的体会出线程与进程的区别。在过去,我们创建的进程一次只能做一件事,要想同时做几件事,我们就得创建多进程。但是有了多线程后,我们在同一个进程里也可以做多件事了。
既然多进程能完成多任务,为什么还要多线程呢?通过前面对进程的学习你知道,多进程之间进行互相沟通还是比较麻烦的,比如内存共享、描述符共享、互斥与同步啊这些,需要专门的进程间通信的技术,写起代码来挺费事。
然而,在同一个进程中的多线程所使用的资源都是共享的,比如内存,文件描述符等等。
2. 线程的资源
在同一个进程中,大部分资源都是所有线程所共享的,比如:
- 可执行程序的代码
- 程序的全局内存
- 堆内存
- 栈
- 文件描述符
但是线程还有一些独有的资源,包含:
- 线程 ID
- 线程自己的一套寄存器值
- 线程运行栈
- 调度优先级和策略
- 信号屏蔽字
- errno 变量
- 线程私有数据
3. 进程与线程的区别
当一个进程被创建的时候,自动就有一个线程在运行,该线程就是主控线程,简称主线程(也就是 main 函数运行的那个线程)。我们可以在主线程里调用创建线程的函数 pthread_create
,当然你也可以在其它线程里调用线程创建函数。
我们需要修正一下以前我们对进程的理解。一直以来我们认为进程就是程序的执行体,实际上,真正的执行体是进程中的线程。进程被创建出来,自动的就包含了一个主线程,真正的执行体是这个线程。
所以,进程是一种空间上的概念,它为所有这些执行体(线程)提供必要的资源(内存、文件描述符、代码等)。而线程,是时间上的概念,它是抽象的、假想的、动态的指令执行过程。
我们可以把进程理解成工厂以及工厂里的各种设备和资源,而线程就是工厂里一个个干活的工人。
4. pthread 线程库
在上一篇我们使用了 pthread 线程库中的函数来创建线程,pthread 是 POSIX.1 中定义的一套线程函数接口,所以这种线程也被称为 POSIX 线程。在我们后面的学习中,都会使用 pthread 线程库来操作线程,包括线程的创建、终止、互斥与同步等等。
要看你的的系统是否支持 POSIX 线程,可以判断宏 _POSIX_THREADS 是否被定义。
5. 实现线程库
为了能更好的理解线程切换和调度原理,你可以阅读专题《实现用户级多线程切换与调度》,这个系列的文章从 0 到 1 实现了一套自己的线程函数及调度框架。纯手工实现多线程的意义在于能够更好的去理解和学习操作系统的源码,掌握操作系统中进程线程的切换和调度原理。
6. 总结
- 理解什么是线程
- 理解进程和线程之间有什么区别
- 什么是 POSIX 线程