Linux--线程控制--线程相关函数--tid--0109 10

news2024/11/20 19:45:59

1.如何理解线程

定义:在一个程序里的一个执行路线就叫做线程(thread)。

更准确的定义是:线程是“一个进程内部的控制序列”。

每个进程都有自己的进程地址空间和task_struct结构体,如果我们通过一定的方式在创建进程的时候,将当前进程的资源(进程地址空间),划分给不同的task_struct。

线程在进程的地址空间内运行,是OS调度的基本单位。

  • 在Linux下,PCB<=其他操作系统的PCB(进程里面只有一个执行流的时候相等)。所以Linux下的进程,统一称之为轻量级进程。
  • Linux没有真正意义上的线程相关的数据结构,Linux是用进程pcb模拟线程的。Linux只能提供轻量级进程的接口。
  • Linux在用户层实现了一套用户层多线程方案,以库的方式——pthread线程库

1.2 进程和线程的初步对比

  • 进程是资源分配的基本单位。
  • 线程是调度的基本单位。
  • 线程共享进程数据,文件描述符、每种信号的处理方式、当前工作目录、用户id和组id
  • 线程拥有自己的一部分数据:线程ID、一组寄存器、栈、errno、信号屏蔽字、调度优先级。
  • 线程切换成本低,因为地址空间不需要切换、页表不需要切换、CPU内部的缓存(L1~L3cache)不用重新读取数据。进程切换会导致cache立即失效,只能重新缓存。
  • 计算密集型应用,为了能在多处理器系统上运行,将计算分解到多个线程中实现
  • 一个线程出问题,那整个进程都会终止。
  • 线程在创建并执行时,线程也是需要进行等待的。不然会出现内存泄漏问题。

1.3 线程的缺点

  • 性能损失。如果计算密集型线程的数量比可用的处理器多,那么可能会有较大的性能损失。增加了额外的同步和调度开销,而可用的资源不变。
  • 健壮性降低。因共享了不该共享的变量而造成不良影响,线程之间是缺乏保护的。
  • 缺乏访问控制。
  • 编程难度提高。

2. 线程相关函数

2.1 创建线程

pthread_create

#include <pthread.h>
int pthread_create(pthread_t *thread,const pthread_arr_t * arrt,
void*(*start_routine)(void*),void*arg)

 参数介绍

thread 线程的id

arrt 线程的属性 先默认nullptr

函数指针 是线程需要去执行的代码的入口函数

arg 传递给函数指针的参数

成功返回0

注意

编译时一定要加 -lpthread      g++ -o $@ $^ -std=c++11 -lpthread

由于回调函数的参数是void*类型 所以想传什么类型都可以,也可以传一个结构体以携带更多的信息给arg。

代码测试及结果

#include <iostream>
#include <string>
#include <cstdio>
#include <unistd.h>
#include <pthread.h>
using namespace std;

void* threadRun(void* args)
{
    const string name=(char*)args;
    while(true)
    {
        cout<<name<<" -> pid: "<<getpid()<<"\n"<<endl;
        sleep(1);
    }
    return (void*)10;
    //不需要返回其他数据时  return nullptr;
}
int main()
{
    pthread_t tid[5];//pthread_t 其实本质就是一个 无符号的长整型
    char name[64];
    for(int i=0;i<5;i++)
    {
        snprintf(name,sizeof(name),"%s-%d","thread",i);//写到哪里 写多少 写什么 
        pthread_create(tid+i,nullptr,threadRun,(void*)name);
        sleep(1);//传参有bug 等待一下
    }
    while(true)
    {
        cout<<"main thread pid"<<getpid()<<endl;
        sleep(3);
    }
    return 0;
}

 所有线程的pid是相同的,那我们查看轻量级进程

ps -aL | grep mythread | head -1 && ps -aL

 LWP : 轻量级进程对应的PID ,PID和LWP一样的是主进程。

2.2 等待线程

pthread_join

#include <pthread.h>
int pthread_join(pthread_t thread, void **retval);

参数介绍

thread 等待线程的tid。

retval 获取回调函数的返回值。

成功返回0,错误为错误码。

测试代码及结果

int main()
{
    pthread_t tid;
    pthread_create(&tid,nullptr,threadRun,(void*)"thread 1" );

    void* ret=nullptr;
    pthread_join(tid,&ret);//阻塞等待新线程 等待完才会往下进行
    cout<<"main thread wait done , main quit..."<<endl;
    return 0;
}

打印返回内容

1. 根据返回值的类型进行强转。注意Linux是64位环境,指针是八字节,不能用int接受。

cout<<(long long)ret<<endl;

2. 直接将ret定义为返回值的类型,在pthread_join中进行强转为(void**)&ret

void* pthreadRun(void* args)
{
    int*dp[5];
    //...
    return (void*)dp;
}
int main()
{
    //...
    int* ret=nullptr;
    pthread_join(tid,(void**)&ret);
}

 2.3 线程退出

如果使用exit();整个进程将退出。

pthread_cancel

#include <pthread.h>
int pthread_cancel(pthread_t thread);

 2.4 线程tid的获取

pthread_self

#include <pthread.h>
int main()
{
    //...
    cout<<pthread_self()<<endl;
}

2.5 __thread 关键字

如果有这样一个全局变量v,我们在线程执行的代码中++v,并打印v和v的地址,在主进程中同样打印v和v的地址。我们发现,主进程中的v和线程中的v是一个值。

但如果我们不想让二者共享这个v,我们就需要添加__thread关键字。

#include<pthread.h>
__thread int v=0;

__thread关键字:修饰全局变量,让每一个线程各自拥有一个全局的变量——线程的局部存储

2.6 分离线程

默认情况下,线程是可以通过pthread_join接口被等待的。否则无法释放资源,从而造成资源泄露。但如果我们不关心线程的返回值,join是一种负担,我们可以告诉系统,当线程退出的时候,自动释放资源。

#include <pthread.h>
int pthread_detach(pthread_t thread);

可以是线程组内其他线程对目标线程进行分离,但更建议线程自己分离.

pthread_detach(pthread_self());

 一个线程如果分离了,就不能再被等待了,pthread_join()会返回错误码


3. pthread_t

是 unsigned long int 的typedef结果,本质上是地址。

为什么说tid是地址?

我们之前在讲线程的特点的时候,说线程要有独立的栈和寄存器等。那我们如何实现线程之间栈的独立性,划分栈空间吗?Linux系统中没有线程的概念,只有轻量级进程,所以如果划分了栈,就与这点相悖。所以独立的栈空间需要由用户层(库)来提供。

 为了让线程更快的找到自己的用户层属性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/159228.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【记录】ChatGPT|近期两次更新一览(更新至2023年1月12日)

如果你还没有使用过ChatGPT&#xff0c;可以先看看我的上一篇文章&#xff1a;【记录】ChatGPT&#xff5c;注册流程、使用技巧与应用推荐&#xff08;更新至2022年12月14日&#xff09;。   昨天晚上&#xff0c;ChatGPT突然很多人都无法登录&#xff0c;包括我。我当时以为…

SpringBoot+Redis+@Cacheable实现缓存功能

SpringBootRedisCacheable实现缓存功能一、pom文件加入Redis与cache的依赖和yml配置二、EnableCaching允许使用注解进行缓存三、Redis配置四、业务逻辑1.UserController2.UserService3.UserServiceImpl4.AdminServiceImpl5.Cacheable和CachePut区别五、测试1.执行saveUser方法2…

剑指offer----C语言版----第十七天----面试题23:链表中环的入口节点

目录 1. 链表中环的入口节点 1.1 环形链表Ⅰ 1.1.1 题目描述 1.1.2解题思路 1.1.3 扩展问题 1.2 环形链表Ⅱ 1.2.1 题目描述 1.2.2 思路分析 1. 链表中环的入口节点 在leetcode上的剑指offer专栏没有收录这道题目&#xff0c;但Leetcode上是有这道题目的&#xff0c;环…

U3D客户端框架之 音效管理器 与 Fmod介绍安装导入Unity

一、Fmod介绍与安装导入Unity 1.Fmod与Unity内置Audio播放器对比 Unity内置的Audio底层使用的是FMOD&#xff0c;但是功能不够齐全&#xff0c;高级一点的功能如混合(Mix)等无法使用&#xff1b; 音效管理应该和Unity工程解耦合&#xff0c;这样子可以减轻音效设计师的负担&a…

ArcGIS基础实验操作100例--实验86矢量面重叠分析

本实验专栏参考自汤国安教授《地理信息系统基础实验操作100例》一书 实验平台&#xff1a;ArcGIS 10.6 实验数据&#xff1a;请访问实验1&#xff08;传送门&#xff09; 空间分析篇--实验86 矢量面重叠分析 目录 一、实验背景 二、实验数据 三、实验步骤 &#xff08;1&am…

初阶指针详解✍

目录1.内存和地址2.指针变量的大小3.指针类型的意义意义1&#xff1a;指针访问权限的大小意义2&#xff1a;指针类型决定指针的步长4.野指针野指针成因如何规避野指针5.指针的运算指针加减整数指针减指针指针的比较运算6.指针与数组的关系7.二级指针1.内存和地址 内存是电脑上特…

2、C语言程序规范

目录 1. 代码缩进 2. 变量、常量命名规范 3. 函数的命名规范 4. #include指令 5. 注释 6. main函数 7.函数返回值 8. 变量赋初值 俗话说&#xff0c;“没有规矩&#xff0c;不成方圆。” 如&#xff1a;第一个程序 #include <stdio.h>void main(){printf("…

基于java Springmvc+mybatis 电影院售票管理系统设计和实现以及文档

基于java Springmvcmybatis 电影院售票管理系统设计和实现以及文档 博主介绍&#xff1a;5年java开发经验&#xff0c;专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 超级帅帅吴 Java毕设项目精品实战案例《500套》 欢迎点赞 收藏 ⭐留…

vue报错汇总

项目场景&#xff1a; 使用vue报错汇总。 1、项目启动不报错也不成功 提示&#xff1a;这里描述项目中遇到的问题&#xff1a; 项目启动时&#xff0c;一直启动不成功&#xff0c;末句提示 98% emitting Copyplugin… 原因分析&#xff1a; 最有可能是因为require或者import了…

系统设计技巧:使用Postgres作为发布/订阅和作业服务器

如果在项目中需要发布/订阅和作业服务器&#xff0c;可以尝试使用 Postgres。它将为您提供大量数据完整性和性能保证&#xff0c;并且不需要您或您的团队学习任何新技术。如果你正在做任何足够复杂的项目&#xff0c;你将需要一个 发布/订阅[1] 服务器来处理事件。本文将向你介…

黑马“兔年限定”春节礼盒准时送达,快来领!

哈咯艾瑞巴蒂&#xff0c;我是播妞前几天一个热搜引起了我的注意# 原来兔年要打384天的工 #看到这标题播妞突然头皮发紧我搜索了一下&#xff0c;原来是......农历癸卯兔年全年共有384天今年的春节是2023年1月22号2024年的春节是2月10号从今年春节到明年的春节算一年由于“闰二…

XCTF:ics-05

测试了所有功能点&#xff0c;大部分没有做出来&#xff0c;只有设备维护中心可以点击 查看源码&#xff0c;发现云平台设备维护中心这里有一个超链接 看到变量传参page&#xff0c;有点像页面文件包含功能&#xff0c;那有可能存在文件包含&#xff0c;测试下&#xff1a; …

ORB-SLAM2 --- LoopClosing::CorrectLoop函数

目录 1.函数作用 2.函数流程 3.code 4.函数解析 4.1 结束局部地图线程、全局BA&#xff0c;为闭环矫正做准备 4.2 根据共视关系更新当前关键帧与其它关键帧之间的连接关系 4.3 通过位姿传播&#xff0c;得到Sim3优化后&#xff0c;与当前帧相连的关键帧的位姿&#xf…

什么是计算机中的高速公路-总线?

文章目录总线是什么&#xff1f;常见总线类型有哪些&#xff1f;总线的串行和并行的区别&#xff1f;数据总线地址总线CPU的寻址能力32位CPU最大支持4G内存&#xff1f;控制总线总线的共享性和独自性系统总线的结构单总线结构双总线结构三总线结构总线传输的四个阶段总线仲裁集…

谷粒商城项目笔记之高级篇(二)

目录1.7 认证服务1.7.1 环境搭建1&#xff09;、创建认证服务微服务2&#xff09;、引入依赖3)、添加相应的域名4&#xff09;、动静分离5&#xff09;、nacos中注册6&#xff09;、配置网关7)、测试访问登录页面8&#xff09;、实现各个页面之间跳转1.7.2 验证码功能1)、验证码…

C++的类介绍(封装特性)

一、类的定义 1.1定义 类是c语言对编程思想的概括深化&#xff0c;其前期的C语言使能面向过程的语言&#xff0c;思想是注重对程序每一步的理解&#xff1b;而面向过程的是C语言之父把生活的类与对象的思想应用于程序设计之中&#xff0c;把程序抽象成一个个对象。 C面向对象…

将时间序列转换为指定的频率并指定填充方法来填充缺失值的DataFrame.asfreq()方法

【小白从小学Python、C、Java】 【计算机等级考试500强双证书】 【Python-数据分析】 时间序列的插值操作 提升序列中时间密度 DataFrame.asfreq() 选择题 关于以下python代码说法错误的一项是? import pandas as pd myIndexpd.date_range(1/12/2023,periods3,freqT) dfpd.D…

深入了解 LinkedBlockingQueue阻塞队列

1. 前言 今天来逐个方法解析下LinkedBlockingQueue. 其实跟上篇文件深入了解ArrayBlockingQueue 阻塞队列很类似。只不过底层实现不同。其实看名字就能看出来到底依据什么实现的。好了&#xff0c;废话不多说了&#xff0c;接下来让我们开始吧 至于API的使用情况跟ArrayBlockin…

JS垃圾回收

什么是GC GC就是Garbage Collection,程序工作过程中会产生很多垃圾&#xff0c;这些垃圾是程序不用的内存或者是之前用过了&#xff0c;以后不会再用的内存空间&#xff0c;而GC就是负责回收垃圾的。当然也不是所有的语言都会自带GC&#xff0c;比如Java、Python、Javascript等…

电脑修改用户(User)文件夹名称

情景&#xff1a;Windows 11 的用户名与 C 盘&#xff08;系统盘&#xff09;中的文件夹名称不对应&#xff08;可能是由于重装系统导致的&#xff09;&#xff0c;例如我笔记本中系统用户名是 “fly”&#xff0c;但文件夹名称却是“16490”。 Step 1&#xff1a;打开Administ…