linux 线程

文章目录

    • 1.线程概念
      • 线程优点
      • 线程缺点
    • 2.Linux线程和进程
    • 3. Linux线程控制
      • 线程创建---pthread_create
      • 线程等待---pthread_join
      • 线程退出
      • 线程分离---pthread_detach

1.线程概念

进程=内核数据结构 + 进程代码和数据
我们的代码在进程中,全部都是串行调用的
进程创建,成本较高(时间和空间),不仅需要创建PCB,页表等,还需要进行初始化,时间和空间成本高,所以多进程的目的是为了多执行流并发执行
地址空间和地址空间上的虚拟地址,本质是一种资源,一个进程的大部分资源都可以通过地址空间来访问
在内核角度,进程是承担分配系统资源的基本实体

当一个程序被执行时,操作系统会为其创建一个进程,并为该进程分配必要的系统资源,如内存空间、设备I/O等。这些资源是进程执行程序所必需的,只有被分配给进程后,才能被进程所使用。

加粗样式
线程是进程内部的一个执行分支,是CPU调度的基本单位,线程在进程地址空间内运行
Linux设计者认为,进程和线程都是执行流,具有极度的相似性,没必要单独设计数据结构和算法,直接复用代码,用进程模拟线程,也就是说,Linux中没有真正的线程
CPU调度时不需要区分进程和线程,都是执行流,在Linux中,所有的调度执行流都叫做轻量级进程(LWP),OS在调度时,使用LWP来进行调度
可以用是 ps -aL 查看轻量级进程
在这里插入图片描述

线程优点

创建一个新线程的代价比创建一个新进程的代价小得多
与进程切换相比,线程之间的切换需要OS做的工作要少很多—CPU内存在cache,切换进程,需要将CPU内的硬件级cache数据丢弃,重新填充
线程占用的资源比进程要少很多

线程缺点

健壮性降低:健壮性主要指的是线程在并发执行过程中,面对各种问题时,能够保持其正常功能和性能的能力,编写多线程程序需要更深入的考虑
缺乏访问控制:进程是访问控制的基本粒度,在一个线程中调用某些OS函数会对整个进程造成影响。
编程难度提高:编写与调试一个多线程程序比单线程程序困难得多

2.Linux线程和进程

  • 进程是承担分配系统资源的基本实体
  • 线程是CPU调度的基本单位
  • 线程私有的数据:
    调度:CPU运行的上下文数据
    常规运行:独立的栈结构
  • 线程在进程地址空间内运行,在同一进程的同一地址空间中,所有线程的数据区(已初始化数据区和未初始化数据区)和代码区都是共享的,定义的全局变量每个线程都可以访问到

3. Linux线程控制

  • Linux中没有真正的线程,只有轻量级进程,所以Linux系统不会有线程相关的系统调用,只有轻量级进程的系统调用
  • 为了用户更好使用,有了pthread库(原生线程库)),将轻量级进程系统调用进行封装,转换为线程相关接口提供给用户。不属于内核,用户级
  • 要使用这些接口,需要包含头文件<pthread.h>,同时编译时指定库 -lpthread

线程创建—pthread_create

在这里插入图片描述
thread:输出型参数,返回线程ID
attr:设置线程的属性,默认设置为NULL即可
start_routine:参数为void*,返回值为void*的函数指针,是线程启动后执行的函数
arg:传给线程启动函数的参数
在这里插入图片描述
pthreads函数成功返回0,失败返回错误码

#include <iostream>
#include <unistd.h>
#include <pthread.h>


void* threadrun(void*)
{
    while(true)
    {
        std::cout << "I am new thread" << std::endl;
        sleep(1);
    }
}

int main()
{
    pthread_t tid;
    pthread_create(&tid, nullptr, threadrun, nullptr);
    while(true)
    {
        std::cout << "I am main thread" << std::endl;
        sleep(1);
    }
    
    return 0;
}

在这里插入图片描述

  • 获取线程ID pthread_self
  • 获取线程ID: 1.创建线程时输出型参数获取 2.pthread_self
#include <iostream>
#include <string>
#include <unistd.h>
#include <pthread.h>

std::string ToHEX(pthread_t tid)
{
    char buff[128];
    snprintf(buff, sizeof(buff) - 1, "%#lx", tid);
    return buff;
}

void* threadrun(void*)
{
    while(true)
    {
        std::cout << "I am new thread, tid :" << ToHEX(pthread_self()) << std::endl;
        sleep(1);
    }
}

int main()
{
    pthread_t tid;
    pthread_create(&tid, nullptr, threadrun, nullptr);
    while(true)
    {
        std::cout << "I am main thread, new thread tid:" << ToHEX(tid) << std::endl;
        sleep(1);
    }

    return 0;
}

在这里插入图片描述

线程等待—pthread_join

线程被创建,也需要被等待,不等待会有内存泄露的问题,同时也需要获取线程的退出信息
在这里插入图片描述
retval:输出型参数,为线程函数的返回值

#include <iostream>
#include <string>
#include <vector>
#include <unistd.h>
#include <pthread.h>

std::string ToHEX(pthread_t tid)
{
    char buff[128];
    snprintf(buff, sizeof(buff) - 1, "%#lx", tid);
    return buff;
}

struct Thread
{
    Thread(pthread_t tid, const std::string& name)
        :_tid(tid), _threadName(name)
    {}
    pthread_t _tid;
    std::string _threadName;
};

void* threadrun(void* args)
{
    std::string* name = static_cast<std::string*>(args);
    int cnt = 10;
    while(cnt--)
    {
        std::cout << *name << " is running...." << std::endl;
        sleep(1);
    }
    return (void*)100;
}

int main()
{
    const int threadNum = 5;
    std::vector<Thread> threads;
    for (int i = 0; i < threadNum; i++)
    {
        pthread_t tid;
        std::string* name = new std::string("thread-" + std::to_string(i + 1));
        pthread_create(&tid, nullptr, threadrun, name);
        threads.emplace_back(tid, *name);
    }
    void* ret;
    for (auto& thread : threads)
    {
        pthread_join(thread._tid, &ret);
        std::cout << thread._threadName << "is quit, return val: " << (long long int)ret << std::endl;
    }
    return 0;
}

在这里插入图片描述

线程退出

    1. 从线程函数直接return
    1. pthread_exit
      在这里插入图片描述
      retval:退出信息
#include <iostream>
#include <string>
#include <vector>
#include <unistd.h>
#include <pthread.h>

void* threadrun(void*)
{
    int cnt = 5;
    while(cnt--)
    {
        std::cout << "线程还有" << cnt << "秒退出" << std::endl;
        sleep(1);
    }
    std::string* ret = new std::string("11111111111111111111111111");
    pthread_exit(ret);
}


int main()
{
    pthread_t tid;
    pthread_create(&tid, nullptr, threadrun, nullptr);

    void* ret;
    pthread_join(tid, &ret);
    std::string* retval = static_cast<std::string*>(ret);
    std::cout << "thread return val: " << *retval << std::endl;

    return 0;
}

在这里插入图片描述
线程调用pthread_exit()终止,pthread_join()所获得的返回值为pthread_exit()的参数

    1. 一个线程调用pthread_cancel终止同一进程中的另一个线程保证新线程已经启动的前提下
      在这里插入图片描述
#include <iostream>
#include <string>
#include <vector>
#include <unistd.h>
#include <pthread.h>

void* threadrun(void*)
{
    while(true)
    {
        std::cout << "new thread running...." << std::endl;
        sleep(1);
    }
}


int main()
{
    pthread_t tid;
    pthread_create(&tid, nullptr, threadrun, nullptr);

    sleep(2);
    pthread_cancel(tid);

     void* ret;
     pthread_join(tid, &ret);
    
     std::cout << "thread return val: " << (long long int)ret << std::endl;

    return 0;
}

在这里插入图片描述
线程被取消,退出信息是-1,-1是一个宏
在这里插入图片描述

线程分离—pthread_detach

在这里插入图片描述

  • 默认情况下,线程是需要被等待的,线程退出后,要对其进行pthread_join操作,否则无法释放资源,造成资源泄露
  • 如果不关心线程返回值,可以分离线程,线程退出时,自动释放资源
    分离是线程的一种工作状态,底层依旧是同一个进程,只是不需要且禁止join了

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

vue+intro.js实现引导功能

前言&#xff1a; 使用 intro.js这个插件&#xff0c;来实现一个引导性的效果&#xff0c;适用场景&#xff0c;比如&#xff1a;新手引导页&#xff0c;操作说明等等 效果图&#xff1a; 官网地址&#xff1a;点我 实现步骤&#xff1a; 1、安装 npm install intro.js --sa…

C++程序员笔试训练

面试题1&#xff1a;使用库函数将数字转换位字符串 考点&#xff1a;c语言库函数中数字转换位字符串的使用 char *gcvt(double number, int ndigit, char *buf);参数说明&#xff1a; number&#xff1a;待转换的double类型数值。 ndigit&#xff1a;保留的小数位数。 buf&am…

AI大模型爆发,你还不学就晚了!抓住时代机遇,快速入门指南!

AI大模型风起云涌&#xff0c;你准备好乘风破浪了吗&#xff1f; 在一个阳光明媚的午后&#xff0c;小李坐在自己的工位上&#xff0c;眼前的代码如同繁星般繁多。他是一名资深的软件工程师&#xff0c;但在最近的技术浪潮中&#xff0c;他却感到了一丝不安。他的朋友圈里&…

绝了!篇篇10万+的AI治愈系插画,完整版项目拆解(附提示词)!

大家好&#xff0c;我是向阳 最近&#xff0c;治愈系插画在小某薯上热度很高&#xff0c;比如这个号&#xff0c;每一篇的笔记数据都不错&#xff0c;2个月时间涨粉7.3万。 然后&#xff0c;我偶然发现&#xff0c;有人把这样的治愈插画用到公某号爆文的配图上&#xff0c;每一…

探索Docker容器网络

Docker容器已经成为现代应用部署的核心工具。理解Docker的网络模型对于实现高效、安全的容器化应用至关重要。在这篇博客中&#xff0c;我们将深入探讨Docker的网络架构&#xff0c;并通过一些代码例子来揭示其底层实现。 Docker网络模式 Docker提供了多种网络模式&#xff0c…

真心建议大家冲一冲新兴领域,工资高前景好【大模型NLP开发篇】

前言 从ChatGPT到新近的GPT-4&#xff0c;GPT模型的发展表明&#xff0c;AI正在向着“类⼈化”⽅向迅速发展。 GPT-4具备深度阅读和识图能⼒&#xff0c;能够出⾊地通过专业考试并完成复杂指令&#xff0c;向⼈类引以为傲的“创造⼒”发起挑战。 现有的就业结构即将发⽣重⼤变…

pxe批量部署linux介绍

1、PXE批量部署的作用及必要性&#xff1a; 1&#xff09;智能实现操作系统的批量安装&#xff08;无人值守安装&#xff09;2&#xff09;减少管理员工作&#xff0c;提高工作效率3&#xff09;可以定制操作系统的安装流程a.标准流程定制(ks.cfg)b.自定义流程定制(ks.cfg(%pos…

使用免费恢复软件恢复已删除的文件

由于删除或 Shift (Command) Delete 而丢失重要文件 通常&#xff0c;当您删除计算机上的文件时&#xff0c;您仍然可以在回收站 (Windows) 或垃圾箱 (Mac) 中找到它。但是&#xff0c;如果删除的文件绕过了回收站&#xff0c;或者您已将其从回收站中清空&#xff0c;则您必须…

全网首发:教你如何直接用4090玩转最新开源的stablediffusion3.0

1.stablediffusion的概述&#xff1a; Stable Diffusion&#xff08;简称SD&#xff09;近期的动态确实不多&#xff0c;但最新的发展无疑令人瞩目。StableCascade、Playground V2.5和Stableforge虽然带来了一些更新&#xff0c;但它们在SD3面前似乎略显黯然。就在昨晚&#x…

基于QT5.12.7的VTK8.2下的VS2015 X64源码编译以及测试

有一段时间没更新博客了&#xff0c;最近在考虑使用VTK作为软件的后处理显示&#xff0c;相比于OSG&#xff0c;VTK在后处理上集成了很多优秀的算法&#xff0c;使用起来比较方便&#xff0c;而且后处理一般不需要太多的交互&#xff0c;所以VTK是一个不错的选择。 之前对VTK了…

FlinkCDC 3.1.0 支持 Flink 1.18.0 版本选择

问题&#xff1a;FlinkCDC 3.1.0 pipeline 与 Flink 1.17.0 可能是因为出现版本不支持的问题&#xff08;已实测&#xff09; 持续报错&#xff1a; -- client log Exception in thread "main" java.lang.BootstrapMethodError: java.lang.NoSuchMethodError: org.a…

AI预测福彩3D采取888=3策略+和值012路或胆码测试6月15日新模型预测第5弹

今天咱们继续验证新模型的8码定位3&#xff0c;目前新模型新算法8码定位经过4次测试&#xff0c;已命中3次&#xff0c;9码定位连续命中4次。咱们重点是预测8码定位3&#xff0b;和值012胆码。有些朋友看到我最近几篇文章没有给大家提供缩水后的预测详情&#xff0c;在这里解释…

SpringCloud2023 - 学习笔记

文章目录 1. 简介1.1 基础知识1.2 组件更替与升级 2. 微服务基础项目构建2.1 创建项目2.2 Mapper4生成代码2.3 支付模块编码2.4 项目完善2.5 订单模块编码2.6 工程重构 3. consul服务注册与发现3.1 consul简介3.2 consul下载安装3.3 微服务入驻3.4 order订单微服务入驻3.5 其他…

Pytorch 卷积神经网络-手写数字识别

卷积神经网络是深度学习中的一个里程碑式的技术&#xff0c;有了这个技术&#xff0c;才会让计算机有能力理解图片和视频信息&#xff0c;才会有计算机视觉的众多应用。 本文讨论卷积神经网络模型&#xff08;CNN&#xff09;的Hello World。前面讨论的是一个二分类问题&#x…

线代知识点总结

目录 一.初等行/列变换 1.计算行列式时&#xff0c;行列变换都可 2.求矩阵的秩时&#xff0c;行列变换都可 3.解线性方程组时&#xff0c;仅能使用初等行变换 4.判定解的情况&#xff0c;单纯求r(A),r(A,b)的过程行列变换都可 5.求向量组极大无关组、线性表出关系&#x…

基于springboot的宠物商城网站

文章目录 项目介绍主要功能截图:部分代码展示设计总结项目获取方式🍅 作者主页:超级无敌暴龙战士塔塔开 🍅 简介:Java领域优质创作者🏆、 简历模板、学习资料、面试题库【关注我,都给你】 🍅文末获取源码联系🍅 项目介绍 基于springboot的宠物商城网站,java项目…

QT QFileDialog文件选择对话框

QT QFileDialog文件选择对话框 选择txt或者cpp文件&#xff0c;读取内容并显示 参考&#xff1a; QT写入文件与读取文件内容_qt往一个文件写东西-CSDN博客 #include "QtFilePreview.h" #include "qfiledialog.h" #include "qfile.h" #includ…

TCGAbiolinks包学习

TCGAbiolinks 写在前面学习目的GDCquery GDCdownload GDC prepare中间遇到的报错下载蛋白质数据 写在前面 由于别人提醒我TCGA的数据可以利用TCGAbiolinks下载并处理&#xff0c;所以我决定阅读该包手册&#xff0c;主要是该包应该是有更新的&#xff0c;我看手册进行更新了&…

IO流及字符集

IO流 作用&#xff1a; 用于读写文件中的数据 分类&#xff1a; 图来自黑马程序员网课 纯文本文件&#xff1a;Windows自带的记事本打开能读懂的文件&#xff0c;word excel不是纯文本文件 图来自黑马程序员网课 FileOutputStream: 操作本地文件的字节输出流&#xff0c;可…

SQLServer 借助Navcate做定时备份的脚本

首先创建SQLServer链接&#xff0c;然后在Query标签种创建一个查询 查询内容如下 use ChengYuMES declare ls_time varchar(1000) declare ls_dbname varchar(1000) set ls_time convert(varchar, getdate(), 112) _ replace(convert(varchar, getdate(), 108), :, )-- 需…