线程相关知识点

news2025/1/19 14:25:47

一、线程

1.1 线程的概念

        线程是轻量级的进程。

        进程是分配资源的最小单位,线程是调度的最小单位。 

        线程不会单独分配内存空间,线程共用进程的资源。

        线程之间通信比较方便,但是不安全。

        多线程没有多进程安全。

        多线程效率比较高。线程创建比较快,公用进程的资源。线程上下文的切换比较迅速,因为线程占用的内存资源少。

        多进程比较浪费资源,多线程节省资源。

        每一个进程中,最少有一个线程,叫做主线程。

        线程使用的是第三方库,需要添加#include<pthread.h>头文件,在编译的时候,需要添加 -lpthread参数

        安装线程man手册:sudo apt-get install manpages*

1.2 线程创建

1.2.1 pthread_create(线程创建的函数)

#include <pthread.h>
int pthread_create(pthread_t *thread,const pthread_attr_t *attr,void *(*start_routine)(void *),void *arg);
功能:创建线程
参数:
    thread:线程号
    attr:线程属性 -- 传NULL即可
    start_routine:线程体 - 在线程体中定义了线程要执行的任务
    arg:给线程传参
返回值:成功返回0,失败返回错误码

1.2.2 线程创建函数的使用示例1(不关注返回值)

#include <my_head.h>
pthread_t tid;

void *thread_func(void *arg){
    while (1)
    {
        printf("线程1\n");
        sleep(1);
    }
    
}
int main(int argc,const char *argv[]){
    int ret = 0;
    ret = pthread_create(&tid,NULL,thread_func,NULL);
    if(ret != 0){
        printf("创建线程失败:%s\n",strerror(ret));
        return -1;
    }
    while (1)
    {
        printf("我是主线程\n");
        sleep(1);
    }
    
    return 0;
}

运行结果:

1.2.3 线程创建函数的使用示例2 (传递参数)

#include <my_head.h>
pthread_t tid1,tid2;
typedef struct Struct{
    char name[32];
    char sex;
    short tall;
}stu_t;

void *thread_func(void *arg){
    while(1){
        printf("线程id = %d\n",*(int *)arg);
        sleep(1);
    }
}
void *thread_func2(void *arg){
    while (1)
    {
        printf("%s %c %hd",((stu_t *)(arg))->name,((stu_t *)(arg))->sex,((stu_t *)(arg))->tall);
        sleep(1);
    }
}
int main(int argc,const char *argv[]){
    int ret = 0;
    stu_t stu1 = {
        .name = "xiaoming",
        .sex = 'm',
        .tall = 180,
    };
    stu_t stu2 = {
        .name = "hong",
        .sex = 'w',
        .tall = 170,
    };
    ret = pthread_create(&tid1,NULL,thread_func2,(void *)&stu1);
    if(ret != 0){
        printf("创建线程失败:%s\n",strerror(ret));
        return -1;
    }
    while (1)
    {
        printf("主线程\n");
        sleep(1);
    }
    return 0;
}

     运行实例:

 

1.3 线程的执行顺序问题

没有顺序,时间片轮询,上下文切换

1.4 线程的内存空间问题

#include<my_head.h>
pthread_t tid1,tid2;

int var1 = 100;


void *thread_func(void *arg){
    while(1){
        printf("var1 = %d\n",var1);//5s之后,输出数值变成200,下面的线程对全局变量数值做了修改
        sleep(1);
    }
}

void *thread_func2(void *arg){
    sleep(5);
    var1 = 200;
}

int main(int argc,const char *argv[]){
    int ret = 0;

    ret = pthread_create(&tid1,NULL,thread_func,NULL);
    if(ret != 0){
        printf("创建线程失败:%s\n",strerror(ret));
        return -1;
    }
    ret = pthread_create(&tid2,NULL,thread_func2,NULL);
    if(ret != 0){
        printf("创建线程失败:%s\n",strerror(ret));
        return -1;
    }

    while(1){
       // printf("我是主线程....\n");
        sleep(1);
    }
    return 0;
}

1.5 pthread_self(获取线程号)

#include <pthread.h>
pthread_t pthread_self(void);
功能:获取线程的线程号
参数:空
返回值:获取到的线程号,这个函数总是调用成功

pthrread_self使用示例

#include <my_head.h>
pthread_t tid1,tid2;
void *thread_func2(void *arg){
    printf("我的线程号%ld\n",pthread_self());
}
int main(int argc,const char *argv[]){
    int ret = 0;
    ret = pthread_create(&tid2,NULL,thread_func2,NULL);
    if(ret != 0){
        printf("创建线程失败:%s\n",strerror(ret));
        return -1;
    }
    while(1){
        sleep(1);
    }
    return 0;
}

运行结果:

2.7 pthread_join(线程资源回收)

#include <pthread.h> -- 所需头文件
int pthread_join(pthread_t thread,void **retval);
功能:阻塞回收指定的线程资源
参数:
    thread:要回收的现成的线程id
    retval:线程退出的状态
返回值:成功返回0,失败返回错误码

pthread_join函数的使用(不传参)

#include <my_head.h>
pthread_t tid1,tid2;
void *thread_func2(void *arg){
    printf("我是子线程,我要结束了\n");
    pthread_exit(NULL);//传参NULL,不反悔退出状态
}
int main(int argc,const char *argv[]){
    int ret = 0;
    while(1){
        ret = pthread_create(&tid2,NULL,thread_func2,NULL);
        if(ret != 0){
            printf("创建线程失败:%s\n",strerror(ret));
            return -1;
        }
        pthread_join(tid2,NULL);
        sleep(1);
    }
    return 0;
}

运行结果:

pthread_join 函数的使用(不传参)

#include <my_head.h>
pthread_t tid1,tid2;
void *thread_func2(void *arg){
    printf("子进程,我要结束了\n");
    pthread_exit(NULL);//传NULL,不返回退出状态
}
int main(int argc,const char *argv[]){
    int ret = 0;
    while(1){
        ret = pthread_create(&tid2,NULL,thread_func2,NULL);
        if(ret != 0){
            printf("创建线程失败:%s\n",strerror(ret));
            return -1;
        }
        pthread_join(tid2,NULL);//不传参NULL
        sleep(1);
    }
    return 0;
}

运行结果:

pthread_join 函数的使用(传参)

#include <my_head.h>
pthread_t tid1,tid2;
void *thread_func2(void *arg){
    int *retval = (int *)malloc(sizeof(int));
    *retval = 100;
    printf("我是子线程,我要结束了\n");
    pthread_exit((void *)retval);
    //传NULL,不反悔退出状态
    //不可传局部变量的地址,会导致数据错误或者程序崩溃
}
int main(int argc,const char *argv[]){
    int ret = 0;
    int *retval;
    ret = pthread_create(&tid2,NULL,thread_func2,NULL);
    if(ret != 0){
        printf("创建线程失败%s\n",strerror(ret));
        return -1;
    }
    pthread_join(tid2,(void **)&retval);
    printf("retval = %d\n",*retval);
    free(retval);
    sleep(1);
    return 0;
}

运行结果:

1.8 pthread_detach(线程分离)

线程的状态分为两种 分离态 和 结合态。

结合态的线程,需要其他线程调用pthread_join为线程回收资源。

分离态的线程,操作系统会自动为线程回收资源。

线程默认的状态:结合态。

#include <pthread.h> -- 所需头文件
int pthread_detach(pthread_t thread);
功能:将线程设置为分离态
参数:
    thread:线程id
返回值:成功返回0,失败返回错误码
#include <my_head.h>
pthread_t tid1,tid2;

void *thread_func2(void *arg){
    pthread_detach(pthread_self());
    //将线程设为分离态,线程结束之后,才做系统自动为其分配资源
    printf("我是子线程,我要结束了\n");
    pthread_exit(NULL);//传NULL,不反悔退出状态
}

int main(int argc,const char *argv[]){
    int ret = 0;
    while(1){
        ret = pthread_create(&tid2,NULL,thread_func2,NULL);
        if(0 != ret){
            printf("创建线程失败:%s\n",strerror(ret));
            return -1;
        }
        sleep(1);
    }
}

运行结果:

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

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

相关文章

嵌入式学习-I/O-Day01

嵌入式学习-I/O-Day01 IO介绍 IO分类 文件IO 标准IO 标准IO的调用逻辑 标准IO缓存机制 标准IO的特点 * 流 定义 流的分类 流指针FILE * 缓存区的分类 * 全缓存—》基于文件 行缓存-》基于终端stdin/stdout 不缓存&#xff1a;stderr 标准IO的函数接口 ​​​​…

小白都来用这款AI绘画神器,IDEOGRAM2.0,轻松画出高质量图片

大家好&#xff01;我是宇航&#xff0c;一位喜欢AI绘画的10年技术专家&#xff0c;专注于输出AI绘画与视频内容 今天给大家介绍一款绝对的生图神器——Ideogram2.0! 不论你是AI小白&#xff0c;手残党还是资深玩家&#xff0c;无论你是做网页设计&#xff0c;电商&#xff0c…

React路由 基本使用 嵌套路由 动态路由 获取路由参数 异步路由 根据配置文件来生成路由

文章目录 React-router的三个版本react-router使用嵌套路由动态路由 获取路由参数Params参数Query参数Location信息 控制跳转地址异步路由根据配置文件生成路由 React-router的三个版本 React-router 服务端渲染使用React-router-dom 浏览器端渲染使用React-router-native Rea…

【STM32CubeMX开发】-2.2-TIM_输出一个PWM信号

目录 1 Tim定时器的时钟源 2 Tim定时器的配置 2.1 PWM配置 2.2 中断配置 3 生成代码 4 测试结果 结尾 1 Tim定时器的时钟源 TIM3的时钟来源自APB1 Timer clocks&#xff0c;时钟树上所有总线频率均设置为了STM32F0能达到的最高频率&#xff0c;此时APB1 Timer clocks …

【CTF Web】Pikachu ../../ Writeup(路径遍历)

目录遍历漏洞概述 在web功能设计中,很多时候我们会要将需要访问的文件定义成变量&#xff0c;从而让前端的功能便的更加灵活。 当用户发起一个前端的请求时&#xff0c;便会将请求的这个文件的值(比如文件名称)传递到后台&#xff0c;后台再执行其对应的文件。 在这个过程中&a…

Diffusion model原理:李宏毅篇(1)

本文是对李宏毅老师相关视频的记录。视频连接:Diffusion Model数学原理(一) 1. 基本概念 slide注释有一个加噪的扩散过程和一个去噪生成图像的过程VAE与Diffusion model有类似的地方。Diffusion model加噪的过程可以看成是VAE的encoder,去噪的过程看成是VAE的decoder2. DD…

【Linux】信号(初版)

信号概念 信号是进程之间发送异步信息的一种方式 在Linux命令行中&#xff0c;我们可以通过ctrl c来终止一个前台运行的进程&#xff0c;其实这就是一个发送信号的行为。我们按下ctrl c是在shell进程中&#xff0c;而被终止的进程&#xff0c;是在前台运行的另外一个进程。…

[2024领航杯] Pwn方向题解 babyheap

[2024领航杯] Pwn方向题解 babyheap 前言&#xff1a; 当然这个比赛我没有参加&#xff0c;是江苏省的一个比赛&#xff0c;附件是XiDP师傅在比赛结束之后发给我的&#xff0c;最近事情有点多&#xff0c;当时搁置了一天&#xff0c;昨天下午想起来这个事情&#xff0c;才开始…

C++容器适配器1-基本使用(stack、queue)

###适配器意思是可以将一种不能用于某种场景的东西经过特殊转换&#xff0c;包装成一个新东西&#xff0c;这个新定西可以用于这个场景&#xff0c;并且还具有之前旧东西的功能作用&#xff1b; stack、queue就是C里面的容器适配器&#xff0c;这两个适配器堆vector和list两个…

前端进阶之路:推荐几本不可错过的前端开发书籍

前端开发是一个不断更新换代的领域&#xff0c;作为一名前端工程师&#xff0c;持续学习和提升自己是至关重要的。阅读专业书籍是系统学习前端知识的一种有效方式。以下是一些前端开发者不可错过的书籍推荐&#xff0c;帮助你巩固基础&#xff0c;拓宽视野&#xff0c;成为更优…

【进阶OpenCV】 (13)--视频物体跟踪

文章目录 物体跟踪一、跟踪器二、代码实现1. 创建CSRT跟踪器实例2. 打开视频文件3. 主循环3.1 读取每一帧3.2 设置跟踪目标3.3 更新跟踪器&#xff0c;获取对象位置3.4 显示视频每一帧 4. 释放资源和关闭窗口5. 完整代码展示 总结 物体跟踪 本篇我们来介绍&#xff0c;如何对移…

Nvidia Jetson Orin平台部署CenterPoint模型

最近尝试将CenterPoint模型部署到Orin平台,网络上教程很多,也很杂乱,于是便整理一版自用。 主要根据NVIDIA Lidar AI Solution进行复现。并在此基础上进行补充 Orin平台: python:3.8 CUDA:11.4 torch:1.14.0 torchvision:0.15.1 TensorRT: 8.5.2.1 在Compile &&a…

第十九篇——复盘:数学给了我什么启示?

目录 一、背景介绍二、思路&方案三、过程1.思维导图2.文章中经典的句子理解3.学习之后对于投资市场的理解4.通过这篇文章结合我知道的东西我能想到什么&#xff1f; 四、总结五、升华 一、背景介绍 数学带给这个世界什么&#xff1f;数学在我们的人生路上意味着什么&#…

Arthas 介绍,阿里开源线上JVM性能监控工具

1.官网 https://arthas.aliyun.com/ arthas (aliyun.com) Arthas 是一款由阿里巴巴开发并开源的 Java 应用诊断工具&#xff0c;主要用于帮助开发人员实时监控、诊断和调优 Java 应用程序。这款工具对于处理复杂的生产环境问题特别有效&#xff0c;尤其在定位那些难以复现的…

面网易后台开发居然遇到了一个困难难度算法题

在提供面经的同学中&#xff0c;竟然有同学在面试网易后台研发的时候遇到了一道困难难度的算法题。 一般来说&#xff0c;大多数面试的算法题都是以中等难度为主&#xff0c;遇到困难难度的算法题也许是公司现在不缺人、也许是在选拔人才、当然也很可能是面试官其实并不想要你…

基于LSTM-Transformer混合模型实现股票价格多变量时序预测(PyTorch版)

前言 系列专栏:【深度学习&#xff1a;算法项目实战】✨︎ 涉及医疗健康、财经金融、商业零售、食品饮料、运动健身、交通运输、环境科学、社交媒体以及文本和图像处理等诸多领域&#xff0c;讨论了各种复杂的深度神经网络思想&#xff0c;如卷积神经网络、循环神经网络、生成对…

【WRF工具】服务器上安装convert_geotiff

【WRF工具】服务器上安装convert_geotiff convert_geotiff简介方法1&#xff1a;下载安装包后下载convert_geotiff依赖库安装库1&#xff1a;libtiff库2&#xff1a;sqlite库3&#xff1a;curl库4&#xff1a;projcmake更新&#xff08;可选&#xff09;库5&#xff1a;geotiff…

mysql--表的约束

目录 理解表的约束和操作 如何理解&#xff1f; 1、空属性null 2、默认值default 3、列描述comment 4、自动填充zorefill 5、主键primary key &#xff08;1&#xff09;创建表时指定可以 &#xff08;2&#xff09;创建表后指定key &#xff08;3&#xff09;删除主…

Cocos Creator导出obj文件用于后端寻路

Cocos Creator 3.8.0 用这个扩展插件 【杨宗宝】两年前写的网格工具&#xff0c;今天将它开源了。 - Creator 3.x - Cocos中文社区carlosyzy_extensions_mesh: Cocos Creator 3.x mesh插件&#xff0c;负责网格数据的导出。合并&#xff0c;拆封等一系列操作 (gitee.com) 下…

Avalonia开发实践(四)——关于Setter优先级的问题

首先看一段样例代码&#xff1a; <StackPanel Orientation"Horizontal" Spacing"50" HorizontalAlignment"Center"><StackPanel.Styles><Style Selector"Button.default"><Setter Property"Background&quo…