线程标识
线程由线程号进行标识。线程号仅在线程所属的进程环境中有效。也就是说属于不同进程的两个线程可能线程号一样。
线程标识用结构体pthread_t tid表示。与线程Id相关的函数如下:
比较两个线程ID:
#include <pthread.h> int pthread_equal(pthread_t tid1,pthread_t tid2); Returns: nonzero if equal, 0 otherwise
获取自身线程ID:
#include <pthread.h> pthread_t pthread_self(void); Returns: the thread ID of the calling thread
创建和终止进程:
创建线程:
#include <pthread.h> int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg); Returns: 0 if OK, error number on failure
tidp: 线程ID
attr:定制线程属性
start_rtn:新线程从start_rtn指向的函数开始执行
arg:传入start_rtn指向函数的参数
线程终止:
线程有三种终止方式:
1)从启动例程返回(return),返回值为线程退出码
2)被同进程的其他线程取消
3)调用pthread_exit
1)调用pthread_exit
#include <pthread.h> void pthread_exit(void *rval_ptr);
启动例程调用pthread_exit 可以退出线程。rval_ptr可以被其他线程通过pthread_join访问到
#include <pthread.h> int pthread_join(pthread_t thread,void **rval_ptr); Returns: 0 if OK, error number on failure
pthread_join 使线程发生阻塞,知道thread指向的线程终止,rval_ptr用于获取终止线程的返回值。如果线程是通过被取消的方式结束,则返回值被置为PTHREAD_CANCELED。
2)被同进程其他线程取消
#include <pthread.h> int pthread_cancel(pthread_t tid); Returns: 0 if OK, error number on failure
3)线程的清理
线程可以构建线程清理程序栈来自定义线程清理程序。(栈:后进先出)
#include <pthread.h> void pthread_cleanup_push(void (*rtn)(void *), void *arg); void pthread_cleanup_pop(int execute);
在三种情况之一,线程清理程序栈被调用
a
.线程调用pthread_exitb.应答其他线程的cancellation请求
c.
execute参数非0
具体使用见后面的example
#include "apue.h" #include "myerr.h" #include <pthread.h> void cleanup(void *arg) { printf("cleanup: %s ", (char *)arg); } void * thr_fn1(void *arg) { printf("thread 1 start "); pthread_cleanup_push(cleanup, "thread 1 first handler"); pthread_cleanup_push(cleanup, "thread 1 second handler"); printf("thread 1 push complete "); if (arg) return((void *)1); pthread_cleanup_pop(0); pthread_cleanup_pop(0); return((void *)1); } void * thr_fn2(void *arg) { printf("thread 2 start "); pthread_cleanup_push(cleanup, "thread 2 first handler"); pthread_cleanup_push(cleanup, "thread 2 second handler"); printf("thread 2 push complete "); if (arg) pthread_exit((void *)2); pthread_cleanup_pop(0); pthread_cleanup_pop(0); pthread_exit((void *)2); } int main(void) { int err; pthread_t tid1, tid2; void *tret; err = pthread_create(&tid1, NULL, thr_fn1, (void *)1); if (err != 0) err_exit(err, "can’t create thread 1"); err = pthread_create(&tid2, NULL, thr_fn2, (void *)1); if (err != 0) err_exit(err, "can’t create thread 2"); err = pthread_join(tid1, &tret); if (err != 0) err_exit(err, "can’t join with thread 1"); printf("thread 1 exit code %ld ", (long)tret); err = pthread_join(tid2, &tret); if (err != 0) err_exit(err, "can’t join with thread 2"); printf("thread 2 exit code %ld ", (long)tret); exit(0); }
执行结果
windeal@ubuntu:~/Windeal/apue$ ./exe thread 2 start thread 2 push complete cleanup: thread 2 second handler cleanup: thread 2 first handler thread 1 start thread 1 push complete cleanup: thread 1 second handler thread 1 exit code 1 thread 2 exit code 2 windeal@ubuntu:~/Windeal/apue$