线程
在传统的UNIX系统中,线程的概念也被使用,但并不是真正的线程,是使用进程模拟的,因此多线程的真正优点没有得到发挥。
与传统的进程相比较,用线程来实现相同功能有如下优点:
1. 系统资源消耗低
2. 速度快
3. 线程间的数据共享比进程间容易得多
为什么需要多线程?
线程是承担调度的基本单位,一个进程可拥有多个线程,它的执行力度比进程更加细致,线程资源共享。
什么是线程
线程:也称轻量级进程(LWP),是执行流的最小单元。而多线程就是指,在一个进程中有多个执行流,在同时执行。
在一个程序里的一个执行路线叫做线程,线程是一个进程内部的控制序列。
从代码执行的角度看,线程就是一个正在运行的代码片段,该代码片段和一个进程内部的其他代码片段可以并发执行。
注意:
在linux中并不存在真正的线程,linux的线程是使用进程模拟的。我们在linux系统中,线程的创建是在内核外进行的,有POSIX提供的线程库实现。因此链接这些线程函数库时要使用编译器命令的”-lpthread”选项。Linux下的线程也叫轻量级进程(LWP)
Linux线程的本质
在linux中,新建的线程并不是在原先的进程中,而是系统通过一个系统调用clone().。该系统copy了一个和原先进程完全一样的进程,并在这个进程中执行线程函数。不过这个copy过程和fork不一样。Copy后的进程和原先的进程共享了所有的变量,运行环境。所以线程是共享全局变量和环境的。
以上线程创建函数在libpthread.so,故编译时 gcc -o 程序名 -lpthread 文件名
进程和线程的区别
进程是资源竞争的基本单位,线程是程序执行的最小单位,是承担调度的基本单位。
由于同一进程的多个线程共享同一地址空间,因此线程之间有相互共享的资源,但是也拥有自己独立的部分:线程ID,独立的上下文数据,栈,errno,信号屏蔽字,调度优先级。
线程之间共享的资源主要有:
1、 地址空间
2、 数据段和代码段
3、 全局变量
4、 文件描述符
5、 信号处理方式(忽略或者有自定义动作)
6、 用户ID和组ID
7、 当前工作目录
线程独享资源主要有:
1、线程id
2、上下文,包括各种寄存器的值,程序计数器和栈指针
3、栈空间
4、errno变量
5、信号屏蔽字
6、调度优先级
进程与线程的区别归纳如下几点:
1. 地址空间:进程间相互独立,每个进程都有自己独立的地址空间,同一进程的个线程间共享地址空间。某个进城内的线程在其他进城内不可见。
2. 通信关系:进程间通信有管道,消息队列,共享内存,信号量。线程间通信可以直接读写全局变量来进行通信。不管是进程还是线程,通信时可能出现数据不一致的情况,需要用同步互斥机制来保证数据的一致性。
3. 切换和调度:由于进程间独占数据代码段等信息,所以切换进程的时候,需要把进程间独占的资源切换去,把要执行的进程资源换进来,而线程是进程的子集,共享大部分资源,切换时只需要保存上下文相关信息就好,所以线程切换的开销比进程切换的开销小。
4. 线程是处理器调度的基本单位,但进程不是
5. 二者均可并发执行
进程线程的关系图
线程的状态
线程主要有三种状态分别是就绪、阻塞、运行
就绪:线程具备运行的所有条件,逻辑上已可以运行,在等待处理机。
阻塞:指线程在等待某一时间的发生,如I/o操作
运行:占有处理器正在运行。
线程的优点
1. 创建线程消耗的资源更少
2. 线程切换的开销更少
3. 充分利用多处理器的可并行数量
4. 线程占用的资源比进程少
5. 在等待慢速I/O操作结束的同时,程序可以执行其他的计算任务
6. 计算密集型应用,为了能在多处理器系统上运行,将计算分解到多个线程中实现
7. I/O密集型应用,为了提高性能,将I/O操作重叠。线程可以同时等待不同的I/O操作
注意:但是尽量不要创建太多线程,线程切换和管理也是需要成本的。
线程的缺点
1. 如果计算机密集型线程比可用处理器多,有可能增加了额外的同步和调度开销,而可用的资源不变。
2. 健壮性降低:编写多线程程序需要考虑的更加全面,有可能共享了不该共享的变量,造成不良影响
3. 缺乏访问控制:进程是访问控制的基本粒度,在一个线程中调用某些系统函数对整个进程造成影响
4. 编写程序难度较高