什么是线程
在早期,unix其实是没有线程的概念,因为它的进程已经做的足够优秀了。但是,随着操作系统行业的发展,其他操作系统,比如windows,都有了线程的存在。于是,很多开发人员就呼吁unix也提供线程功能。unix为了顺应开发人员的呼吁,于是也开发出线程。
但对于Unix/linux而言,线程不是一个全新的东西,而是直接拿进程过来改改,将进程改头换面,就变成了线程。其本质依然是进程。
相关概念:
LWP: light weight process,轻量级的进程;
进程:有独立的地址空间,有进程控制块PCB;
线程:也有PCB,但没有独立的地址空间,而是和其它线程共享;
进程与线程区别:
区别在于是否有独立地址空间。实际上,一个进程可以有多个线程,所有的线程共享进程的地址空间。
在lInux环境下,线程是最小的执行单位,因为线程本质就是进程,CPU会将线程与进程一视同仁,为它们分配相同的时间轮片。因此,拥有多个线程的进程将有更高的执行效率。
而进程是最小的资源分配单位,因为不管一个进程里有多少个线程,它的地址空间都是0~4G,所以可看成是只有一个线程的进程。
Linux内核线程实现原理
- 前文提到,线程是轻量级的进程(light weight process),同样具有PCB,创建线程与创建进程所使用的底层函数是一样的,都是clone;
- 从内核里看进程和线程是一样的,都有各自不同的PCB,但是PCB中指向内存资源的三级页表是相同的,也就是说,所有的线程都是共享进程资源的;
- 进程可以蜕变成线程。当一个进程创建了一个线程之后,其自身即蜕变为一个线程;
- 线程可看作寄存器和栈的集合。除了在用户空间外,PCB里还有内核栈,用于保存线程切换时的相关信息;
- 在Linux环境下,线程是最小的执行单位,进程是最小的资源分配单位。
查看指定进程的线程信息:
ps -Lf pid
对于进程来说,每个进程都有0~4G地址空间,不同的进程相同的虚拟地址可以反复使用而不冲突。原因是他们虽然虚拟地址一样,但是页目录、页表、物理页面各不相同。所以,相同的虚拟地址,映射到不同的物理页面内存单元,最终访问到的是不同的物理页面。
但是,线程不同。两个线程具有各自独立的PCB,但共享同一个页目录,也就共享同一个页表和物理页面。所以两个PCB共享一个地址空间。
线程共享资源
- 文件描述符表
- 每种信号的处理方式
- 当前工作目录
- 用户ID和组ID
- 内存地址空间 (.text/.data/.bss/heap/共享库、注意,没有栈空间)
线程非共享资源
- 线程id
- 处理器现场和栈指针(内核栈)
- 独立的栈空间(用户空间栈)
- errno变量
- 信号屏蔽字
- 调度优先级
线程优/缺点
优点:
- 提高程序并发性。线程与进程在内核里地位相同,将得到相同的时间轮片,可提高并发性;
- 开销小。线程是轻量级的进程;
- 数据通信、共享数据方便。所有的线程都共享相同的进程资源,方便数据的共享。
缺点:
- 使用库函数,不稳定。线程原语所使用的是库函数,而非系统调用,相对不稳定;
- 调试、编写困难、gdb不支持。但是可以通过printf打印相关信息进行调试;
- 对信号支持不好。千万不要使用信号+线程,极大增加复杂度。
虽然线程也有一些缺点,但是它的优点相对突出,缺点均不是硬伤。所以相较而言利大于弊,能够使用线程的地方推荐尽量使用线程。
---------------
码字不易,点个赞再走呗~
我是良许,世界500强外企 Linux 开发工程师,专业生产 Linux 干货。欢迎关注我的公众号「良许Linux」,回复「1024」获取最新最全的技术资料,回复「入群」进入高手如云技术交流群;提供永久免费 CSDN 资料下载服务。