本文测试代码的运行环境:
Centos7 x86_64
Kernel 3.10.0-693.5.2.el7.x86_64
gcc 版本 4.8.5
CPU:2 核
线程概念
线程是运行在进程之中的一个处理任务的分支,一个进程都包括一个主线程。
进程:资源分配、管理的基本单位(管理内存、管理打开的文件等)。
线程:调度、执行的基本单位。
在 Linux 中线程也叫做轻量级进程 ==LWP==。
每次创建一个新的进程,会分配一个新的虚拟地址空间。
每次创建一个新的线程,线程共用原来的虚拟地址空间。
从 Linux 内核的角度来说,其实它并没有线程的概念。Linux 把所有线程都当做进程来实现,它将线程和进程不加区分的统一到了 task_struct 中。
线程之间共用的资源
- 虚拟地址空间。
- 文件描述符表。
线程创建的时候,加上了 CLONE_VM 标记,这样==线程的内存描述符将直接指向父进程的内存描述符。==
1 | if (clone_flags & CLONE_VM) { |
线程之间不共用的资源
- 栈。
- 上下文信息(寄存器信息)。
- errno(每个线程有自己单独的错误码)。
对于 Linux 进程或者说主线程,其 stack 是在 fork 的时候生成的,实际上就是复制了父亲的 stack 空间地址,然后写时拷贝 (cow) 以及动态增长。
然而对于主线程生成的子线程而言,其 stack 将不再是这样的了,而是事先固定下来的。
线程栈不能动态增长,一旦用尽就没了,这是和生成进程的 fork 不同的地方。
线程的优点
相比于进程来说:
- 创建和销毁开销更小。
- 切换调度的开销更小。
- 线程占用的资源更小。
多线程程序能够充分利用多核处理器。
栗子:==因为我的虚拟机是 2 核的,所以 CPU 最多使用是 200%==
线程的缺点
- 程序的健壮性降低,一个线程的异常终止会导致整个进程异常终止。
- 编程 && 调试难度增加(引入了线程安全问题)。
线程的用途
- 提升 CPU 密集型程序执行效率。
- 提高 IO 密集型程序的体验。
- 通过网络进行 IO。
- 响应 UI 界面。
EOF