pthread.h 库的使用(1)

线程属性 - 线程连接和分离

概述

pthread_join函数阻塞主线程直到指定的线程终止。“连接”是一种在线程间完成同步的方法。
pthread_detach函数可以显式用于分离线程。

使用pthread_create的attr参数可以显式的创建可连接或分离的线程,典型四步如下:
1. 声明一个pthread_attr_t数据类型的线程属性变量
2. 用pthread_attr_init初始化改属性变量
3. 用pthread_attr_setdetachstate设置可分离状态属性
4. 完了后,用pthread_attr_destroy释放属性所占用的库资源

函数用法

创建线程:pthread_creade
int pthread_create(pthread_t * thread, 
                   const pthread_attr_t * attr,
                   void * (*start_routine)(void *), 
                   void *arg);

参数:
thread - 指向线程的指针。
attr - 指向线程属性的指针。可设置为NULL。
start_routine - 用于线程化的函数指针。
arg - 指向函数参数的指针。

返回值:线程标识id
退出线程:pthread_exit
void pthread_exit(void *retval);

参数:
retval - 指向线程返回值的指针。
获取调用的线程号:pthread_self
pthread_t pthread_self(void);
返回调用线程标识号,返回类型为pthread_t
比较线程标识号:thread_equal
int pthread_equal(pthread_t t1, pthread_t t2);
//返回两个线程标识号是否相等
一次初始化:pthread_once

在多线程环境中,有些事仅需要执行一次。通常当初始化应用程序时,可以比较容易地将其放在main函数中。但当你写一个库时,就不能在main里面初始化了,你可以用静态初始化,但使用一次初始化(pthread_once)会比较容易些。
在多线程编程环境下,尽管pthread_once()调用会出现在多个线程中,init_routine()函数仅执行一次,究竟在哪个线程中执行是不定的,是由内核调度来决定。

int  pthread_once(pthread_once_t  *once_control,  void  (*init_routine) (void));
线程取消:pthread_cancel

pthread_cancel调用并不等待线程终止,它只提出请求。线程在取消请求(pthread_cancel)发出后会继续运行

int pthread_cancel(pthread_t thread);
发送sig信号:pthread_kill
/*
pthread_kill并不是结束进程的意思,而是向指定ID的线程发送一个信号,只是大部分信号的默认动作是终止进程的运行。
如果线程不处理该信号,则按照信号默认的行为作用于整个进程。信号值0为保留信号,作用是根据函数的返回值判断线程是不是还活着。
pthread_kill的返回值:成功(0) 线程不存在(ESRCH) 信号不合法(EINVAL)
*/
int pthread_kill(pthread_t thread,int sig);
主线程挂起直至目标进程返回:pthread_join
int pthread_join(pthread_t thread, void **retval);

参数:
thread - 线程id,标识唯一线程。
retval - 用户定义的指针,用来存储被等待线程的返回值。

返回值:0代表成功。若失败,返回的则是错误号。
线程分离:pthread_detach
/*
一般情况下,线程终止后,其终止状态一直保留到其它线程调用pthread_join获取它的状态为止。但是线程也可以被置为detach状态,这样的线程一旦终止就立刻回收它占用的所有资源,而不保留终止状态。不能对一个已经处于detach状态的线程调用pthread_join,这样的调用将返回EINVAL。如果已经对一个线程调用了pthread_detach就不能再调用pthread_join了。
通常情况下,若创建一个线程不关心它的返回值,也不想使用pthread_join来回收资源(调用pthread_join的进程会阻塞),就可以使用pthread_detach,将该线程的状态设置为分离态,使线程结束后,立即被系统回收。
主线程退出了,“分离线程”还是一样退出。只是“分离线程”的资源是有系统回收的。
*/

int pthread_detach(pthread_t tid);

//pthread_t tid:  分离线程的tid
//返回值:成功返回0,失败返回错误号。
初始化属性对象:pthread_attr_init
int pthread_attr_init(pthread_attr_t *attr);
销毁属性对象:pthread_attr_destroy
int pthread_attr_destroy(pthread_attr_t *attr);

参数:
attr - 指向线程属性对象的指针。

返回值:0代表成功。若失败,返回的则是错误号。
设置属性对象的分离状态:pthread_attr_setdetachstate
int pthread_attr_setdetachstate(const pthread_attr_t *attr,
                                int *detachstate);
参数:
attr - 指向线程属性对象的指针。
detachstate - 设置可分离(PTHREAD_CREATE_DETACHED)或可连接属性(PTHREAD_CREATE_JOINABLE)。

示例代码

#include <pthread.h> 
#include <stdio.h> 
#include <stdlib.h>
#define NUM_THREADS  4 

void *Print(void *threadid) 
{ 
    printf("Thread %d is running\n", *(int*)threadid); 
    free(threadid);
    threadid = NULL;
    pthread_exit(NULL); 
} 

int main (int argc, char *argv[]) 
{ 
    pthread_t thread[NUM_THREADS]; 
    pthread_attr_t attr; 
    int rc, t; 

    pthread_attr_init(&attr); 

    //your code here
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 
    //end of your code

    for(t=0; t<NUM_THREADS; t++) 
    { 
        int* id = (int*)malloc(sizeof(int));
        *id = t;
        printf("Creating thread %d\n", t); 
        rc = pthread_create(&thread[t], &attr, Print, (void*)id);   
        if (rc) 
        { 
            printf("ERROR; return code from pthread_create() is %d\n", rc); 
            exit(-1); 
        } 
    } 

    pthread_attr_destroy(&attr); 
    for(t=0; t<NUM_THREADS; t++) 
    { 
        //your code here
        rc = pthread_join(thread[t], NULL); 
        //end of your code

        if (rc) 
        { 
            printf("ERROR; return code from pthread_join() is %d\n", rc); 
            exit(-1); 
        } 
        printf("Completed join with thread %d\n", t); 
    } 

    pthread_exit(NULL); 
} 
阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页