一、理解线程
线程(thread)
操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务
透过进程虚拟地址空间,可以看到进程的大部分资源,将进程资源合理分配给每个执行流,就形成了线程执行流
二、线程的优缺点
优点:
创建线程和线程之间切换的代价都比进程相关操作代价小
可以发挥多处理器的强大性能
在等待慢速I/O结束的同时,程序可执行其他的任务
CPU密集型应用,将运算任务分解到多个线程中
(但是如果线程数量远远超出CPU的核数量,反而会使得任务效率下降,因为频繁的切换线程消耗时间)
对于I/O密集型应用,当一个线程进行I/O操作时CPU空暇,可以启用其他线程继续使用CPU,提高CPU使用率
缺点:
线程调度时,要保存线程状态,频繁调度会造成性能损失
需要考虑线程安全问题
三、线程控制
POSIX线程库:
POSIX线程(英语:POSIX Threads,常被缩写为Pthreads)是POSIX的线程标准,定义了创建和操纵线程的一套API。
实现POSIX 线程标准的库常被称作Pthreads,一般用于Unix-likePOSIX 系统,如Linux
与线程有关的函数构成了一个完整的系列,绝大多数函数的名字都是以“pthread_”开头
使用这些函数要引入头文<pthread.h>
链接线程函数库时要使用编译器命令的“-lpthread”选项
创建线程
函数原型:
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void * (*start_routine)(void*), void *arg);
参数 :
thread:线程ID的地址
attr:设置线程的属性,attr为NULL表示使用默认属性
start_routine:是个函数地址,线程启动后要执行的函数
arg:传给线程启动函数(start_routine指向的函数)的参数
返回值:
成功返回0,失败返回错误码
查看线程的指令
ps -aL
举例:
这里的LWP标识线程,操作系统通过这个标识区分调度线程
查看线程ID
pthread_t pthread_self();
线程终止
- 从线程函数return。这种方法对主线程不适用,从main函数return相当于调用exit
- . 线程可以调用pthread_ exit终止自己
void pthread_exit(void *value_ptr);
- 一个线程可以调用pthread_ cancel终止同一进程中的另一个线程,一般是主线程取消其他线程
int pthread_cancel(pthread_t thread);
线程等待
已经退出的线程,其空间没有被释放,仍然在进程的地址空间内
创建新的线程不会复用刚才退出线程的地址空间
所以需要线程等待
函数原型:
int pthread_join(pthread_t thread, void **value_ptr);
函数参数说明:
- 如果thread线程通过return返回,value_ ptr所指向的单元里存放的是thread线程函数的返回值。
- 如果thread线程被别的线程调用pthread_ cancel异常终掉,value_ ptr所指向的单元里存放的是常数PTHREAD_ CANCELED。
- 如果thread线程是自己调用pthread_exit终止的,value_ptr所指向的单元存放的是传给pthread_exit的参数。
- 如果对thread线程的终止状态不感兴趣,可以传NULL给value_ ptr参数。
线程分离
默认情况下,线程退出后需要对其进行pthread_join操作,否则无法释放资源,从而造成系统泄漏。
如果不关心线程的返回值,可以分离线程,线程分离后线程退出时会自动释放线程资源。
int pthread_detach(pthread_t thread);
可以是线程组内其他线程对目标线程进行分离,也可以是线程自己分离:
pthread_detach(pthread_self());