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 *);

  1. 参数一:pthread_t * 表示线程ID,声明方式pthread_t tid;

  2. const pthread_attr_t * 表示线程的参数, 一般为NULL,在涉及线程关系复杂情况下会使用

  3. void * ()(void )表示线程开始时执行的函数,如void fun(void),也可使用类的静态函数

  4. 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);
//解锁
​

!!

  1. 对共享资源操作前一定要获得锁。

  2. 完成操作以后一定要释放锁。

  3. 尽量短时间地占用锁。

  4. 如果有多锁, 如获得顺序是ABC连环扣, 释放顺序也应该是ABC。

  5. 线程错误返回时应该释放它所获得的锁。

条件信号

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总结相关推荐

  1. 给线程变量pthread_t *thread动态分配空间

    线程的创建和使用 线程的创建是用下面的几个函数来实现的. #include <pthread.h>int pthread_create(pthread_t *thread,pthread_ ...

  2. thread_t 数组 linux,首页 C#如何打印pthread_t

    好的,这似乎是我的最终答案. 我们有2个实际问题: 如何获取较短的唯一ID以供线程记录. 无论如何,我们需要为线程打印真实的pthread_t ID(至少链接到POSIX值). 1.打印POSIX I ...

  3. C语言多线程教程(pthread)(线程创建pthread_t,指定线程run方法pthread_create,加mutex锁,解锁,伪共享 false sharing【假共享】)

    [C语言]多线程程序入门教程 文章目录 查看pthread_create()函数文档 · Demo1 单线程(创建线程pthread_t .创建线程run方法pthread_create) · Dem ...

  4. pthread_t描述说明

    在posix线程api中,通过pthread_self(void) 函数获取当前线程的id 线程id的类型为pthread_t pthread.h 第267行声明了pthread_self (void ...

  5. linux 线程 pthread_t 和 线程 tid 的区别

    Linux中,每个进程有一个pid,类型pid_t,由getpid()取得. Linux下的POSIX线程也有一个id,类型 pthread_t,由pthread_self()取得,该id由线程库维护 ...

  6. Linux——一文彻底了解进程id和线程id的关系(什么是pid、tgid、lwp、pthread_t)

    目录 一.内核层面:pid & tgid 二.函数调用层面:getpid & gettid & pthread_self 三.用户层面:PID & LWP(TID) 四 ...

  7. 从 pthread_t 获得 PID 和 TID

    pthread_t 其实是一个结构体指针,里面包含了 TID 和 PID,找出它的偏移量就行.在 Ubuntu 16.04.3 x64上测试通过. int get_tid_from_pthread(p ...

  8. 根据pthread_t获取pid_t的tid(线程的pid)

    线程的id Linux下的线程本质是轻量级进程(LWP),因此真正的线程id实际上是该线程的pid(pid_t),而posix库中的pthread_t只是应用层描述线程对象的数据结构的指针(内存地址) ...

  9. CUDA 7流简化并发

    CUDA 7流简化并发 异构计算是指有效使用系统中的所有处理器,包括CPU和GPU.为此,应用程序必须在多个处理器上同时执行功能.CUDA应用程序通过在流(按顺序执行的命令序列)中,执行异步命令来管理 ...

最新文章

  1. 链表问题6——环形单链表的约瑟夫问题(初阶)
  2. 《结对-结对编项目作业名称-开发环境搭建过程》
  3. NLPCC:预训练在小米的推理优化落地
  4. Redis cluster集群:原理及搭建
  5. python中使用连续关系运算符_解释一下Python中的关系运算符
  6. k8s 创建、切换、删除namespace
  7. Servlet之间的跳转(MVC模式)
  8. 一周学会php 视频,一周学会PHP视频 普通下载
  9. \x75\x73\x65\x20\x73\x74\x72\x69\x63\x74解码
  10. HBase-2.0 MOB解决海量图片存储方案
  11. java 中 isb啥意思_isb官网-新版下载
  12. Unity给小鳄鱼洗澡2D流体水实现
  13. 叉积的证明_矢量叉乘分配律的几何证明
  14. java当中的定时器的4种使用方式(delay,period)
  15. R语言的修仙之道--R语言之后天境界
  16. qq邮箱 android,QQ邮箱(com.tencent.androidqqmail) - 6.2.1 - 应用 - 酷安
  17. 单片机音乐盒c语言源程序,51单片机八音盒源程序(汇编语言)
  18. 需求分析和数据分析那些事。
  19. hapi入门简介(入门实践)----净土小沙弥学hapi.js_第二篇
  20. A brief introduction to complex analysis

热门文章

  1. uniapp微信小程序瀑布流布局
  2. pytorch神经网络实现
  3. Nachos实验实现线程id、限制线程数和更改调度算法(按优先级调度)
  4. 信息技术发展史及其趋势
  5. java用account类型定义两个变量_java 编程
  6. [个人笔记]origin学习 APP功能
  7. Hadoophbase监控页面未授权访问漏洞处理方案验证过程实现
  8. 如何批量查询谷歌PR权重是多少?谷歌PR权重怎么批量查询
  9. 熵值法的信息熵值、效用值如何计算?
  10. 直坐标机械手的优缺点都有哪些?