APUE学习笔记——11 线程基础

来源:互联网 发布:合理用药软件系统 编辑:程序博客网 时间:2024/04/29 05:27

线程标识

线程由线程号进行标识。线程号仅在线程所属的进程环境中有效。也就是说属于不同进程的两个线程可能线程号一样。
线程标识用结构体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_exit
b.应答其他线程的cancellation请求
c. execute参数非0
具体使用见后面的example
#include "apue.h"#include "myerr.h"#include <pthread.h>voidcleanup(void *arg){        printf("cleanup: %s\n", (char *)arg);}void *thr_fn1(void *arg){        printf("thread 1 start\n");        pthread_cleanup_push(cleanup, "thread 1 first handler");        pthread_cleanup_push(cleanup, "thread 1 second handler");        printf("thread 1 push complete\n");        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\n");        pthread_cleanup_push(cleanup, "thread 2 first handler");        pthread_cleanup_push(cleanup, "thread 2 second handler");        printf("thread 2 push complete\n");        if (arg)                pthread_exit((void *)2);        pthread_cleanup_pop(0);        pthread_cleanup_pop(0);        pthread_exit((void *)2);}intmain(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\n", (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\n", (long)tret);        exit(0);}           



执行结果
windeal@ubuntu:~/Windeal/apue$ ./exe thread 2 startthread 2 push completecleanup: thread 2 second handlercleanup: thread 2 first handlerthread 1 startthread 1 push completecleanup: thread 1 second handlerthread 1 exit code 1thread 2 exit code 2windeal@ubuntu:~/Windeal/apue$ 















0 0