pthread线程库介绍
pthread 库是 POSIX 线程(Portable Operating System Interface for uniX threads)库的简称,它提供了一套创建和管理线程、以及线程间同步的机制。pthread 库是 UNIX 系统上实现多线程编程的一个标准接口,也被广泛支持在类 UNIX 系统(Linux 和 macOS)中。
头文件
#include <pthread.h>
1.创建线程
新建线程id对象
pthread_t t1;
获取线程id
pthread_t pthread_self(void); // 返回当前线程的线程ID
创建线程函数
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
参数1:线程id对象的指针,创建线程成功时,将线程id写入这个指针指向的内存中
参数2:线程的属性, 一般情况下使用默认属性即可, 写NULL
参数3:函数指针,是回调函数,线程运行时执行该函数
参数4:线程执行函数的参数,多参数可用结构体传入
返回值:函数执行成功返回0,失败返回对应的错误号
2.线程退出
如果想让线程退出,又需要等待其他子线程,不立即释放虚拟地址的内存(针对主线程),就可以调用线程退出函数。只要调用该函数当前线程就马上退出了,并且不会影响到其他线程的正常运行,不管是在子线程或者主线程中都可以使用
void pthread_exit(void *retval);
参数:线程退出的时候携带的数据,当前子线程的主线程会得到该数据。如果不需要使用,指定为NULL
3.线程回收
子线程退出的时候其内核资源主要由主线程回收,主线程可调用pthread_join()来回收自行车资源。
如果还有子线程在运行,调用该函数就会阻塞,子线程退出函数解除阻塞进行资源的回收,函数被调用一次,只能回收一个子线程,如果有多个子线程则需要循环进行回收。
int pthread_join(pthread_t thread, void **retval);
参数1:要被回收的子线程的线程ID
参数2:二级指针, 指向一级指针的地址, 是一个传出参数, 这个地址中存储了子线程pthread_exit() 传递出的数据,如果不需要这个参数,可以指定为NULL
返回值:线程回收成功返回0,回收失败返回错误号
回收子线程数据
子线程退出的时候可以使用pthread_exit()的参数将数据传出,在回收这个子线程的主线程中可以通过phread_join()的第二个参数来接收子线程传递出的数据。接收数据有如下多种处理方式
- 使用子线程栈
子线程回调函数中,创建存储数据的结构体,通过pthread_exit()传出。主线程通过phread_join()的第二个参数来获取数据。 - 使用全局变量
位于同一虚拟地址空间中的线程,虽然不能共享栈区数据,但是可以共享全局数据区和堆区数据,因此在子线程退出的时候可以将传出数据存储到全局变量、静态变量或者堆内存中。不推荐使用全局变量,动态创建/销毁子线程时使用全局变量来回收数据也不可行。 - 使用主线程栈
主线程创建主线程时通过pthread_create()的第四个参数将存储数据的结构体传给子线程,子线程写入数据后通过pthread_exit()传出。
4.线程分离
在某些情况下,程序中的主线程有属于自己的业务处理流程,如果让主线程负责子线程的资源回收,调用pthread_join()只要子线程不退出主线程就会一直被阻塞,主要线程的任务也就不能被执行了。
在线程库函数中为我们提供了线程分离函数pthread_detach(),调用这个函数之后指定的子线程就可以和主线程分离,当子线程退出的时候,其占用的内核资源就被系统的其他进程接管并回收了。线程分离之后在主线程中使用pthread_join()就回收不到子线程资源了。
int pthread_detach(pthread_t thread);
主线程中调用了pthread_detach()后,主线程可以不用调用pthread_join()回收子线程了,子线程回调函数中可以调用pthread_exit()或者在return NULL执行完毕时退出
5.其他线程函数
5.1线程取消
在线程A中想要杀死另外一个线程B,分为两个步骤:
- 在线程A中调用pthread_cancel(),指定线程B的线程ID,但线程B不会被立即杀死
- 在线程B中进程一次系统调用(从用户区切换到内核区),否则线程B可以一直运行
int pthread_cancel(pthread_t thread);
参数:要杀死的线程的线程ID
返回值:函数调用成功返回0,调用失败返回非0错误号
- 系统调用:直接调用Linux系统函数,C/C++的库函数如printf、scanf会调用相关的系统函数
5.2线程ID比较
Linux中线程ID本质就是一个无符号长整形,因此可以直接使用比较操作符比较两个线程的ID,但是线程库是可以跨平台使用的,在某些平台上 pthread_t可能不是一个单纯的整形,这中情况下比较两个线程的ID必须要使用比较函数
int pthread_equal(pthread_t t1, pthread_t t2);
参数:t1 和 t2 是要比较的线程的线程ID
返回值:如果两个线程ID相等返回非0值,如果不相等返回0
本文为总结归纳个人笔记,转载自爱编程的大丙的博客
标签:调用,函数,主线,回收,C语言,线程,pthread,多线程 From: https://www.cnblogs.com/cpp101/p/18404098