LInux的Posix的线程控制

来源:互联网 发布:seo教学 编辑:程序博客网 时间:2024/06/06 18:59

一,线程控制图

主线程<——>|工作队列 |<—-> 工作1 <—>工作2 <—>工作3
线程1<——> |工作队列 |<—-> 工作1 <—>工作2 <—>工作3
线程2<——>|工作队列 |<—-> 工作1 <—>工作2 <—>工作3
线程3<——>|工作队列 |<—-> 工作1 <—>工作2 <—>工作3

二,线程的标识符

  与进程标识符类似,每一个线程都有一个在进程中唯一的线程标识符(线程ID),其用数据类型 pthread_t 来表示的,该数据类型在Linux中其实就是一个无符号长整型数据。LInux提供了两个函数用于对线程标识符,其标准调用格式说明如下:
#include <pthread.h>pthread_t pthread_self(void);
pthread_self函数用于获取线程自身的线程标识符,其返回值是线程自身的线程标识符。pthread_equal函数用于比较两个线程标识符,其标准调用格式说明如下:
#include <pthread.h>int pthread_equal(pthread_tid, pthread_t tid2);

三,线程控制的相关函数

使用gcc编译多线程程序是, 必须与pthread函数库链接,在终端下编译使用下列 gcc -lpthread

1,pthread_create函数

文档说明

NAME       pthread_create - create a new threadSYNOPSIS       #include <pthread.h>       int pthread_create(pthread_t *thread, const pthread_attr_t *attr,                          void *(*start_routine) (void *), void *arg);       Compile and link with -pthread.DESCRIPTION       The  pthread_create()  function  starts  a  new  thread  in the calling       process.  The new thread starts execution by invoking  start_routine();       arg is passed as the sole argument of start_routine().       The new thread terminates in one of the following ways:       * It  calls  pthread_exit(3),  specifying  an exit status value that is         available  to  another  thread  in  the  same  process   that   calls         pthread_join(3).

一个例子

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <pthread.h>#include <unistd.h>pthread_t ntid; //线程id//打印标识符的函数void printds(const char *s){    pid_t pid; //进程标识符    pthread_t tid;  //线程标识符    pid = getpid(); // 获取进程标识符id    //获取线程标识符的id    tid = pthread_self();      printf("%s pid, %u tid %u (0x%x)\n", s, (unsigned int)pid, (unsigned int)tid, (unsigned int)tid);  //打印进程和线程id}//线程中开始运行的函数void *thr_fn(void *arg){    printds("new thread:");    return ((void*)0);}int main(void){    int err;    err = pthread_create(&ntid, NULL, thr_fn, NULL);  //创建一个线程    // 如果出错误打印财务标号    if (err != 0)    {        printf("can't create thread %s\n", strerror(err));    }    //打印主线程号    printds("main thread:");    sleep(1);    exit(0);    return 0;}

pthread_create线程效果图

可以看到标识符为7738的进程创建了两个标识符分别为 2274588416和2266298112 的线程。

2,pthread_exit函数
进程可以调用exit系列函数退出当前进程, 线程也可以通过如下3种方式退出, 子啊不终止整个进程的情况下停止线程的控制流
1,线程只是从启动列程种返回,返回值是线程的退出码。
2,线程可以被同一个进程中的其他进程终止。
3,线程调用pthread_exit函数退出
Linux内核提供pthread_exit函数用于主动退出线程, 其在LInux函数库种原型是:

NAME       pthread_exit - terminate calling threadSYNOPSIS       #include <pthread.h>       void pthread_exit(void *retval);       Compile and link with -pthread.DESCRIPTION       The pthread_exit() function terminates the calling thread and returns a       value via retval that (if the  thread  is  joinable)  is  available  to       another thread in the same process that calls pthread_join(3).       Any  clean-up handlers established by pthread_cleanup_push(3) that have       not yet been popped, are popped (in the reverse of the order  in  which       they  were pushed) and executed.  If the thread has any thread-specific       data, then, after the clean-up handlers have been executed, the  corre‐       sponding destructor functions are called, in an unspecified order.

3,pthread_join函数 我的理解就是没有pthread_join函数就执行pthread_create函数
如果当一个线程已经执行完成之后, 可以被其他的线程了阻塞挂起,过后等待指定的线程调用pthread_exit,以从启动列程中返回或被取消,LInux内核可以调用pthread_join函数来完成对线程阻塞,其在LInux函数库中的原型是:

NAME       pthread_join - join with a terminated threadSYNOPSIS       #include <pthread.h>       int pthread_join(pthread_t thread, void **retval);       Compile and link with -pthread.DESCRIPTION       The pthread_join() function waits for the thread specified by thread to       terminate.  If that thread has already terminated, then  pthread_join()       returns immediately.  The thread specified by thread must be joinable.       If  retval  is  not NULL, then pthread_join() copies the exit status of       the target thread (i.e., the value that the target thread  supplied  to       pthread_exit(3))  into the location pointed to by *retval.  If the tar‐       get thread was canceled, then PTHREAD_CANCELED is placed in *retval.       If multiple threads simultaneously try to join with  the  same  thread,

返回:如果调用成功,函数返回0, 反之返回一个非0值

例子:

#include <stdio.h>#include <string.h>#include <stdlib.h>#include <unistd.h>#include <pthread.h>void print_msg(char *ptr);int main(void){    pthread_t thread1, thread2;    int i, j;    void *retval;    char *msg1 = "This is the frist thread\n";    char *msg2 = "This is the second thread\n";    pthread_create(&thread1, NULL, (void *)(&print_msg),(void *)msg1);    pthread_create(&thread2, NULL, (void *)(&print_msg), (void *)msg2);  //创建两个线程    pthread_join(thread1, &retval);    pthread_join(thread2, &retval);    return 0;}//打印信息函数, 线程从这个函数开始执行void print_msg(char *ptr){    int i;    for( i = 0; i < 10; i++)    {        //连续输出10个字符串        printf("%s\n", ptr);     }}

运行效果图
效果图

4,pthread_cancel函数

pthread_cancel函数

返回:如果操作成功返回0,失败返回对应错误码

5,pthread_cleanup_push和pthread_cleanup_pop函数
当调用pthread_cancel函数取消了一个线程之后,需要调用相应的函数对进程退出之后的环境继续清理,
这里写图片描述

1,调用pthread_exit函数的时候
2,响应取消请求的时候
3,用非execute参数调用pthread_cleanup_pop的时候

6,pthread_detach函数

这里写图片描述