当前位置: 首页 > news >正文

【Linux】线程基本概念,线程控制

目录

基本概念

重新理解进程

线程真实存在吗?

问题解答

线程资源

线程控制

线程创建

如何全面看待线程函数传参

如何看到线程函数返回

线程查询

线程等待

线程终止

线程分离


基本概念

线程(thread)是指在单个进程内,多路并行执行的创建和管理单元;

重新理解进程

在没有学习线程的时候,我们学的进程=内核数据结构+程序的代码和数据;每个进程系统都会为其分配task_struct(PCB),mm_struct(虚拟地址空间),页表来描述和管理进程;

上面的整个才是进程,进程是程度系统资源分配的基本实体;

而线程其实就是进程内的执行流;和之前的进程对比,之前的进程就是内部只有一个执行流的进程!

线程真实存在吗?

在windows中存在真正的进程tcb,而在Linux中并不存在真正的进程,Linux中是用进程来模拟线程!!!

因为复原PCB,同PCB来统一表示执行流,这样的话就不需要为线程单独设计数据结构和调度算法了;像进程一样,线程在程序中有独立,并发的执行路径,每个线程都有它自己私有的栈空间,自己的程序计数器,自己的寄存器,但是他们共享全局数据区,文件描述符等;

问题解答

既然线程用PCB来模拟,那CPU会不会区分task_struct是线程还是进程呢

不做区分,CPU统一将他们看做执行流;Linux中执行流统一被称为轻量级进程;

那么,既然有了多进程,为什么要有多线程呢

  • 进程的创建成本高,创建线程的成本低
  • 线程调度成本低
  • 删除线程成本低

为什么说线程调度成本低呢?

主要原因是在进程切换时,由于线程共享进程的内存空间和资源,cpu的cache中数据往往有效,因此减少了因cache不命中导致的缺页中断开销。

既然线程这么好用,为什么要有进程呢?

虽然线程有很多优势,但也不是毫无代价的.事实上,有些最可怕的bug就是由多线程引起的.设计,编写,理解以及最重要的----调试多线程程序,这些复杂度都是远远高于单个线程的进程.                      最主要的原因:多个虚拟的处理器,但是只有一个虚拟化内存实例,当一个线程同步失败,就会使整个进程运行出错以及程序崩溃;

线程资源

线程共享资源:

  • 进程地址空间
  • 文件描述符表
  • 信号处理方式
  • 当前工作目录
  • 用户ID和组ID

线程私有资源:

  • 线程ID
  • 私有栈空间(重要)
  • 一组寄存器(重要)
  • 程序计数器
  • errno变量
  • 调度优先级
  • 信号屏蔽字

线程控制

线程创建

pthread_create:创建线程

#include <iostream>
#include <unistd.h>
#include<pthread.h>
using namespace std;void *pthreadRun(void *args)
{while(true){cout<<"I am "<<(const char *)args<<endl;sleep(1);}return nullptr;
}
int main()
{pthread_t tid;pthread_create(&tid,nullptr,pthreadRun,(void *)"thread-1");while(true){cout<<"I am main thread"<<endl;sleep(1);}return 0;
}

运行结果:

如何全面看待线程函数传参

给线程传参可以是任意类型,也可以是类对象类型;

void* 指针可以指向任意类型的数据;

具体的void*内容可以看下面的文章:

c语言---指针(1)-CSDN博客

(1)

运行结果: 

(2)不推荐

 

运行结果: 

既然不推荐的话,怎么优化呢?

    ThreadData *td =new ThreadData();td->name="thread";td->num="1";
如何看到线程函数返回
  • 只考虑正确的返回,不考虑异常,因为异常了,整个进程就崩溃了,包括主线程
  • 可以传任意参数,也可以是任意类对象

运行结果:

线程查询

怎么查询线程有没有创建成功呢?

ps -aL:查询线程

ps ajx:查询进程

我们会发现同一个进程下创建的多线程的PID是一样的,但是每个线程的LWP是不一样的;其实OS调度时看到是LWP并不是PID,我们在没有学习线程的时候说的是PID,和现在的说法不是冲突了吗?其实并不是我们之前创建的不管是多进程还是单进程,在进程中都是只有一个执行流的,那是PID和LWP是相同的,所以我们之前所说的PID,其实看到还是LWP只不过LWP和PID一样;学完线程后,我们以后就要说LWP了;

怎么查询线程的LWP呢?

void *pthreadRun(void *args)
{cout<<"tid :"<<pthread_self()<<endl;while(true){cout<<"I am "<<(const char *)args<<endl;sleep(1);}return nullptr;
}

运行结果: 

线程等待

我们期望主线程先退出还是新线程最后退出?   ---->  当然是主线程了,那如何保证main thread最后退出呢?

join来保证,这时就要用到pthread_join来等待新线程;

int main()
{pthread_t tid;int n=pthread_create(&tid,nullptr,pthreadRun,(void *)"thread-1");if(n!=0){cout<<strerror(errno)<<endl;return 1;}//期望谁最后退出?主线程,还是新线程  -->main thread 如何保证?n = pthread_join(tid,nullptr);if(n==0){cout<<"main thread wait sucess"<<endl;}return 0;
}

运行结果: 

 

线程终止

在进程的学习时,我们学过进程的终止有:

  • return
  • exit
  • 信号

那线程的终止有哪些呢?

1、自然退出:线程函数return

2、pthread_exit()                                                                                                                                    我们不能用exit()来进行线程的退出,如果一个线程退出时,用了exit,那么整个进程就会退出,因为exit是用来终止进程的;

3、pthread_cancel :取消一个线程                                                                                                        

线程分离

既然进程有SIGCHLD信号可以让进程不等待,那线程有没有类似的可以让线程也不等待?

当然有了,就是pthread_detach;

  1. 一个线程被创建默认是joinable的,必须被join
  2. 如果一个线程被分离,线程的工作状态处于分离状态,那么就不需要/不必要被join的,但是依旧属于进程内部,只是不需要等待了而已;分离不等于分家;                                            

以上就是线程的基本概念,线程控制的全部内容!!!


http://www.mrgr.cn/news/55682.html

相关文章:

  • LED计数电路综合实验
  • C++面向对象编程学习
  • ruoyi域名跳转缓存冲突问题(解决办法修改:session名修改session的JSESSIONID名称)
  • AI大模型是否有助于攻克重大疾病?
  • Unity DOTS中的Archetype与Chunk
  • WEB前端使用标签制作网页
  • 深度学习--CNN实现猫狗识别二分类(附带下载链接, 长期有效)
  • [while循环]k的幂
  • js实现两个变量交换
  • 座舱软件开发“道与术”
  • 04,perl
  • navigate连接opengauss
  • Linux系统:tac命令
  • 速盾:免费cdn加速节点是什么?
  • 【数学二】多元函数微积分学-多元函数的微分
  • 算法01----移动零(C++)
  • 股票最大利润2
  • Linux文件你不知道的那些事,搞清楚磁盘空间占用的问题
  • 明源云ERP报表服务GetErpConfig.aspx接口存在敏感信息泄露
  • java时间类--Period时间差计算场景2-年月日时分秒
  • Springboot项目控制层注释
  • Axure大屏可视化模板:打造跨领域数据分析平台的原型设计案例
  • 10月20日
  • PMP敏捷专题课:敏捷实践指南
  • pushgateway的快速使用教程(附Java版通用推送代码)
  • EWM 库存盘点