pthread_t总结
pthread_t 相关知识点总结
首先说明一下,在Linux编写多线程程序需要包含头文件 本人在linux环境下运行的代码
pthread_t 只能在 类UNIX平台线程表示方式 ,c++11 std::thread 能跨平台
#include <pthread.h>
创建线程
pthread_create(pthread_t *, const pthread_attr_t *, void *(*)(void *), void *);
pthread_create
pthread_create(pthread_t *, const pthread_attr_t *, void ()(void *), void *);
参数一:pthread_t * 表示线程ID,声明方式pthread_t tid;
const pthread_attr_t * 表示线程的参数, 一般为NULL,在涉及线程关系复杂情况下会使用
void * ()(void )表示线程开始时执行的函数,如void fun(void),也可使用类的静态函数
void* 为第三个参数所代表的函数的参数,即void* fun(void)中第二个void 返回值为0表示成功,其他为错误
#include <stdio.h> #include <unistd.h> //调用 sleep() 函数 #include <pthread.h> //调用 pthread_create() 函数 void *ThreadFun(void *arg) { if (arg == NULL) {printf("arg is NULL\n");}else {printf("%s\n", (char*)arg);}return NULL; } int main() {int res;char *str="create two";pthread_t myThread1,myThread2; //定义两个表示线程的变量(标识符)//创建 myThread1 线程res = pthread_create(&myThread1, NULL, ThreadFun, NULL);if (res != 0) {printf("线程创建失败");return 0;}printf("thread1=%d res=%d \n",myThread1,res);//创建 myThread2 线程res = pthread_create(&myThread2, NULL, ThreadFun,(void*)str);if (res != 0) {printf("线程创建失败");return 0;}printf("thread1=%d res=%d \n",myThread2,res);return 0; } 运行结果为: arg is NULL thread1=-136837568 res=0 //第一个线程数据 res=0 表示成功 create two thread1=-145230272 res=0
终止线程
void pthread_exit(void *); //终止当前的线程(内部终止线程) int pthread_cancel(pthread_t thread); //其他线程发送信号要求终止thread 线程
pthread_exit
void pthread_exit(void *);
参数是out类型 可以获取退出线程的返回值
默认属性的线程执行结束后并不会立即释放占用的资源,直到整个进程执行结束,所有线程的资源以及整个进程占用的资源才会被操作系统回收。
所以这个函数仅仅是退出线程 并不保证回收线程
void * 是指线程返回的数据,int res =pthread_join(myThread, &ret); ret为线程返回的数据
pthread_cancel
int pthread_cancel(pthread_t thread);
过于复杂 详细请看这个地方
事前声明 :不要随便用这个
如果 pthread_cancel() 函数成功地发送了 Cancel 信号,返回数字 0;
反之如果发送失败,函数返回值为非零数。
对于因“未找到目标线程”导致的信号发送失败,函数返回 ESRCH 宏(定义在<errno.h>
头文件中,该宏的值为整数 3)。
使用前提
若是在整个程序退出时,要终止各个线程,应该在成功发送 CANCEL 指令后,使用 pthread_join 函数,等待指定的线程已经完全退出以后,再继续执行;否则,很容易产生 “段错误”。
!!!!!!
虽然发送信号但并不一定能终止 比如线程在while
解决办法
pthread_testcancel();
若是在整个程序退出时,要终止各个线程,应该在成功发送 CANCEL 指令后,使用 pthread_join 函数,等待指定的线程已经完全退出以后,再继续执行;否则,很容易产生 “段错误”。
//pthread_testcancel(); #include <stdio.h> #include <unistd.h> //调用 sleep() 函数 #include <pthread.h> //调用 pthread_create() 函数 void *ThreadFun(void *arg) { int a=0;while(true){//pthread_testcancel();printf("ending %d \n",a);a++;}return NULL; } int main() {int res; pthread_t myThread1; //定义两个表示线程的变量(标识符)//创建 myThread1 线程res = pthread_create(&myThread1, NULL, ThreadFun, NULL);if (res != 0) {printf("线程创建失败");return 0;}pthread_cancel(myThread1); pthread_join(myThread1,NULL);return 0; }
释放线程
pthread_join
int pthread_join(pthread_t thread, void ** retval);
函数功能:堵塞调用它的线程 ,结束后释放子线程资源
1.thread 参数用于指定接收哪个线程的返回值;
2.retval 参数表示接收到的返回值,如果 thread 线程没有返回值,又或者我们不需要接收 thread 线程的返回值,可以将 retval 参数置为 NULL。(exit)
一个线程执行结束的返回值只能由一个 pthread_join() 函数获取,当有多个线程调用 pthread_join() 函数获取同一个线程的执行结果时,哪个线程最先执行 pthread_join() 函数,执行结果就由那个线程获得,其它线程的 pthread_join() 函数都将执行失败。
pthread_detach
int pthread_detach(pthread_t thread); 成功:0;失败:错误号
*作用:*从状态上实现线程分离,注意不是指该线程独自占用地址空间。
线程分离状态:指定该状态,线程主动与主控线程断开关系。线程结束后(不会产生僵尸线程),其退出状态不由其他线程获取,而直接自己自动释放(自己清理掉PCB的残留资源)。网络、多线程服务器常用。
进程若有该机制,将不会产生僵尸进程。僵尸进程的产生主要由于进程死后,大部分资源被释放,一点残留资源仍存于系统中,导致内核认为该进程仍存在。(*注意进程没有这一机制*)
僵尸线程:指工作完毕(任务函数执行完了) 线程不释放。
也可使用 pthread_create函数参2(线程属性)来设置线程分离。
一般情况下,线程终止后,其终止状态一直保留到其它线程调用pthread_join获取它的状态为止(或者进程终止被回收了)。但是线程也可以被置为detach状态,这样的线程一旦终止就立刻回收它占用的所有资源,而不保留终止状态。不能对一个已经处于detach状态的线程调用pthread_join,这样的调用将返回EINVAL错误(22号错误)。也就是说,如果已经对一个线程调用了pthread_detach就不能再调用pthread_join了。
总结
join 堵塞调用它的线程 ,结束后释放子线程资源
deatch 可以让其任务执行完毕后自动释放,而不是成为僵尸线程,释放后不需要也不能调用join
互斥锁
pthread_mutex_t
同一个pthread_mutex_t 在多个地区划分多个地区 ,比如在有个线程在执行地区一 ,那么地区二执行也会被堵塞。
pthread_mutex_t //创建互斥锁 int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr); //后面的参数为设定默认互斥锁属性 成功返回0 int pthread_mutex_destroy(pthread_mutex_t *mutex); //销毁互斥锁 成功返回0 pthread_mutex_lock(pthread_mutex_t *mutex); //上锁 pthread_mutex_unlock(pthread_mutex_t *mutex); //解锁
!!
对共享资源操作前一定要获得锁。
完成操作以后一定要释放锁。
尽量短时间地占用锁。
如果有多锁, 如获得顺序是ABC连环扣, 释放顺序也应该是ABC。
线程错误返回时应该释放它所获得的锁。
条件信号
pthread_cond_t
int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t *restrict attr); //初始化 第二个参数同 int pthread_cond_destroy(pthread_cond_t *cond); // 销毁 int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex); //当线程调用pthread_cond_wait()函数时,会将调用线程放到等待条件的线程列表上,并原子的对互斥量解锁(这样就不会死锁)。 //当pthread_cond_wait()返回时,互斥量再次锁住。 int pthread_cond_signal(pthread_cond_t * cond); //我们使用两个函数可以通知线程条件已经满足。pthread_cond_signal函数至少能唤醒一个等待该条件的线程。 //pthread_cond_broadcast函数能唤醒等待该条件的所有线程。 int pthread_cond_broadcast(pthread_cond_t * cond);
测试代码
#include<iostream> #include<string> #include<thread> #include <unistd.h> using namespace std; pthread_cond_t cond; pthread_mutex_t mutex;void* text(void *arg){printf("wate front\n");pthread_cond_wait(&cond,&mutex);cout<<"text ::"<<endl;pthread_mutex_unlock(&mutex); return nullptr;}; int main() { pthread_t thread; pthread_cond_init(&cond,NULL); pthread_mutex_init(&mutex,nullptr); pthread_create(&thread,NULL,text,NULL); sleep(1); pthread_cond_signal(&cond); pthread_join(thread,nullptr); system("pause"); return 0; } //睡眠一秒后自动释放
pthread_t总结相关推荐
- 给线程变量pthread_t *thread动态分配空间
线程的创建和使用 线程的创建是用下面的几个函数来实现的. #include <pthread.h>int pthread_create(pthread_t *thread,pthread_ ...
- thread_t 数组 linux,首页 C#如何打印pthread_t
好的,这似乎是我的最终答案. 我们有2个实际问题: 如何获取较短的唯一ID以供线程记录. 无论如何,我们需要为线程打印真实的pthread_t ID(至少链接到POSIX值). 1.打印POSIX I ...
- C语言多线程教程(pthread)(线程创建pthread_t,指定线程run方法pthread_create,加mutex锁,解锁,伪共享 false sharing【假共享】)
[C语言]多线程程序入门教程 文章目录 查看pthread_create()函数文档 · Demo1 单线程(创建线程pthread_t .创建线程run方法pthread_create) · Dem ...
- pthread_t描述说明
在posix线程api中,通过pthread_self(void) 函数获取当前线程的id 线程id的类型为pthread_t pthread.h 第267行声明了pthread_self (void ...
- linux 线程 pthread_t 和 线程 tid 的区别
Linux中,每个进程有一个pid,类型pid_t,由getpid()取得. Linux下的POSIX线程也有一个id,类型 pthread_t,由pthread_self()取得,该id由线程库维护 ...
- Linux——一文彻底了解进程id和线程id的关系(什么是pid、tgid、lwp、pthread_t)
目录 一.内核层面:pid & tgid 二.函数调用层面:getpid & gettid & pthread_self 三.用户层面:PID & LWP(TID) 四 ...
- 从 pthread_t 获得 PID 和 TID
pthread_t 其实是一个结构体指针,里面包含了 TID 和 PID,找出它的偏移量就行.在 Ubuntu 16.04.3 x64上测试通过. int get_tid_from_pthread(p ...
- 根据pthread_t获取pid_t的tid(线程的pid)
线程的id Linux下的线程本质是轻量级进程(LWP),因此真正的线程id实际上是该线程的pid(pid_t),而posix库中的pthread_t只是应用层描述线程对象的数据结构的指针(内存地址) ...
- CUDA 7流简化并发
CUDA 7流简化并发 异构计算是指有效使用系统中的所有处理器,包括CPU和GPU.为此,应用程序必须在多个处理器上同时执行功能.CUDA应用程序通过在流(按顺序执行的命令序列)中,执行异步命令来管理 ...
最新文章
- 链表问题6——环形单链表的约瑟夫问题(初阶)
- 《结对-结对编项目作业名称-开发环境搭建过程》
- NLPCC:预训练在小米的推理优化落地
- Redis cluster集群:原理及搭建
- python中使用连续关系运算符_解释一下Python中的关系运算符
- k8s 创建、切换、删除namespace
- Servlet之间的跳转(MVC模式)
- 一周学会php 视频,一周学会PHP视频 普通下载
- \x75\x73\x65\x20\x73\x74\x72\x69\x63\x74解码
- HBase-2.0 MOB解决海量图片存储方案
- java 中 isb啥意思_isb官网-新版下载
- Unity给小鳄鱼洗澡2D流体水实现
- 叉积的证明_矢量叉乘分配律的几何证明
- java当中的定时器的4种使用方式(delay,period)
- R语言的修仙之道--R语言之后天境界
- qq邮箱 android,QQ邮箱(com.tencent.androidqqmail) - 6.2.1 - 应用 - 酷安
- 单片机音乐盒c语言源程序,51单片机八音盒源程序(汇编语言)
- 需求分析和数据分析那些事。
- hapi入门简介(入门实践)----净土小沙弥学hapi.js_第二篇
- A brief introduction to complex analysis