首页 > 代码库 > APUE学习笔记——11 线程基础

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

线程标识

线程由线程号进行标识。线程号仅在线程所属的进程环境中有效。也就是说属于不同进程的两个线程可能线程号一样。
线程标识用结构体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>
void
cleanup(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);
}
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\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 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$ 

















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