第十一章:线程
11.1:引言
本章介绍多线程的使用
11.2:线程概念
典型的Unix进程可以看作只有一个控制线程:一个进程在同一时刻只做一件事情。
11.3:线程标识
每个线程跟进程一样,都有一个线程ID来标识。
#include <pthread.h> int pthread_equal(pthread_t tid1, pthread_t tid2); // 判断两个线程ID是否相等,若相等,返回非0,否则返回0 pthread_t pthread_self(void); // 返回调用线程的线程ID
11.4:线程创建
默认一个进程只包含有个线程,如果要实现多线程,首先得创建新的线程,可以使用函数pthread_create来实现。
#include <pthread.h> // 若成功返回0,否则返回错误编号 int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void*(*start_rtn)(void), void *restrict arg);
如果成功,tidp指向的内存保存线程ID,attr是线程属性,可以为NULL,start_rtn是线程函数,arg是传递给线程函数的参数。
实例:11.1 测试线程ID
11.5:线程终止
如果进程中任一线程调用了exit、_exit、_Exit,那么整个进程就会终止。与此类似,如果信号的默认动作是终止进程,那么信号发送到线程会终止整个进程。
单个线程可以通过下列三种方式退出,在不终止整个进程的情况下停止它的控制流:
1.线程只是从启动例程中返回,返回值是线程的退出码。
2.线程可以被同一个进程中的其他线程取消。
3.线程调用pthread_exit()。
#include <pthread.h> void pthread_exit(void *rval_ptr);
rval_ptr是一个无类型指针,与传给启动例程的单个参数类似。进程中的其他线程可以调用pthread_join来访问这个指针。
#include <pthread.h> int pthread_join(pthread_t thread, void **rval_ptr); // 若成功返回0,否则返回错误编号
调用线程将一直阻塞,直到指定的线程调用pthread_exit()、从启动例程返回或被取消。
实例:11-2 获得线程退出状态
实例:11-3 pthread_exit参数的不正确使用
线程可以通过调用pthread_cancel函数来请求取消同一进程中的其他进程。
#include <pthread.h> int pthread_cancel(pthread_t tid); // 若成功则返回0,否则返回错误编号
注意:pthread_cancel并不等待线程终止,它仅仅提出请求。
线程可以安排它退出时需要调用的函数,这与进程可以用atexit函数安排进程退出时需要调用的函数是类似的。这样的函数称为线程清理处理程序(thread cleanup handler)。线程可以建立多个清理处理程序。处理程序记录在栈中,也就是说它们的执行顺序与它们注册时顺序相反。
#include <pthread.h> void pthread_cleanup_push(void (*rtn)(void*), void *arg); void pthread_cleanup_pop(int execute);
当线程执行以下动作时调用清理函数,调用参数为arg,清理函数rtn的调用顺序是由pthread_cleanup_push函数来安排的。
1.调用pthread_exit时。
2.相应取消请求时。
3.用非零execute参数调用pthread_cleanup_pop时。
如果execute参数置为0,清理函数将不被调用。无论哪种情况,pthread_cleanup_pop都将删除上次pthread_cleanup_push调用建立的清理处理程序。
实例:11-4 线程清理处理程序
默认情况下,线程的终止状态会保存到对该线程调用pthread_join,如果线程已经处于分离状态,线程的底层存储资源可以在线程终止时被立即回收。当线程分离时,并不能用pthread_join函数等待它的终止状态。对分离状态的线程进行pthread_join的调用会产生失败,返回EINVAL。pthread_detach调用可以用于使线程进入分离状态。
#include <pthread.h>
int pthread_detach(pthread_t tid);
分离状态--即该线程在终止时就可以回收其资源。
11.6:线程同步
1.互斥量
2.避免死锁
3.读写锁
4.条件变量
11.7:小结
在本章中介绍了线程的概念,讨论了现有的创建线程和销毁线程的POSIX原语;此外,还介绍了线程同步的问题,讨论了三种基本的同步机制:互斥、读写锁以及条件变量,了解如何使用它们来保护共享资源。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。