《UNIX环境高级编程》(APUE) 笔记第十一章 - 线程

Github 地址

1. 线程概念

典型的 UNIX进程 可以看成只有一个 控制线程 :一个进程在某一时刻只能做一件事情。有了 多个控制线程 ,就可以把进程设计成在某一时刻能够做不止一件事,每个线程处理各自独立的任务。

每个线程都包含有表示执行环境所必需的信息

进程中表示线程的 线程 ID

一组寄存器值

调度优先级和策略

信号屏蔽字

errno 变量

线程私有数据

一个进程所有信息对该进程的所有线程都是共享的

可执行程序的代码

程序的全局内存和堆内存

文件描述符

线程的优点

每个线程在进行事件处理时可以采用 同步编成模式 ,同步编程模式要比异步编程模式简单得多

多个进程必需使用操作系统提供的复杂机制才能实现内存和文件描述符的共享。而多个线程自动地可以访问相同的存储地址空间和文件描述符

有些问题可以分解从而提高整个程序的吞吐量。有多个线程时,相互独立的任务可以交叉进行(任务的处理过程互不依赖),此时只需要为每个任务分配一个单独的线程

交互的程序同样可以通过使用多线程来改善响应时间,多线程可以把程序中处理用户输入输出的部分与其他部分分开

2. 线程 ID

每个线程都有一个 线程 ID ,线程 ID 只在它所属的进程上下文中才有意义。用 pthread_t 数据类型来表示线程 ID ,Linux 中使用无符号长整型表示。

pthead_equal 函数对两个线程 ID 进行比较:

#include <pthread.h> int pthread_equal(pthread_t tid1, pthread_t tid2); //返回值:若想等,返回非0数值;否则,返回0

线程可调用 pthread_self 函数获得自身的线程ID:

#include <pthread.h> pthread_t pthread_self(void); 3. 线程创建

新增的线程通过调用 pthread_create 函数创建:

#include <pthread.h> int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg); //返回值:若成功,返回0;否则,返回错误编号

pthread_create 成功返回时,新创建线程的线程 ID通过 \(tidp\) 返回。\(attr\) 参数用于定制各种不同的线程属性,如果为 NULL ,则使用默认属性。

新创建的线程从 \(start\_rtn\) 函数的地址开始运行。若需要向 \(start\_rtn\) 函数传递的参数有一个以上,需要把这些参数放到一个结构中,然后把这个结构的地址作为 \(arg\) 参数传入。

线程创建时并不能保证哪个线程会先运行,可能是新创建的线程,也可能是调用线程。

4. 线程终止

如果 进程中的任意线程 调用了 exit_Exit 或者 _exit ,那么整个进程就会终止。如果 信号处理的默认动作是终止进程 ,那么发送到线程的信号就会终止整个进程 。

单个线程可以通过 \(3\) 种方式退出(不终止整个进程):

线程可以简单地从启动例程中退出,返回值是线程的退出码

线程可以被同一进程中的其他线程取消( pthread_cancel

线程调用 pthread_exit

pthread_exit 函数用于线程退出:

#include <pthread.h> void pthread_join(pthead_t thread, void *rval_ptr); //返回值:若成功,返回0;否则返回错误编号

pthread_join 用于等待一个线程的结束:

#include <pthread.h> int pthread_join(pthread_t thread, void **rval_ptr); //返回值:若成功,返回0;否则,返回错误编号

pthead_join 的调用线程将一直阻塞,直到指定的线程调用 pthread_exit 、从启动例程中返回或被取消。如果线程简单地从它的启动例程返回,\(rval\_ptr\) 就包含返回码。如果线程被取消,由 \(rval\_ptr\) 指定的内存单元就设置为 PTHREAD_CANCELED 。若将 \(rval\_ptr\) 设置为 NULL ,调用 pthread_join 函数可以等待指定的线程终止,但并不获取线程的终止状态。

可以通过 pthread_join 自动把线程置于分离状态,这样资源就可以恢复。

默认情况下,线程的终止状态会保存直到对该线程调用 pthread_join ,如果线程已被 分离 ,线程的底层存储资源可以在线程终止时被立即收回。

可以调用 pthread_detach 分离线程:

#include <pthread.h> int pthread_detach(pthread_t tid); //返回值:若成功,返回0;否则,返回错误编号

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpjgyx.html