【Linux多线程】认识多线程创建线程

文章目录

  • 什么是多线程
    • 为什么称linux下的线程是轻量级进程呢?
  • 线程的优点
  • 线程的缺点
  • 线程异常
  • 线程和进程
  • 创建线程
    • 1.pthread_create
    • 2.pthread_self

什么是多线程

进程是正在运行的程序的实例,而线程(thread)是进程中的一个执行路线。一个进程可以拥有多个线程。从程序的角度上来说,线程是一个独立运行程序的片段。当程序运行时,进程把大部分资源合理分配给每个执行流(线程),且所有线程共享进程的地址空间,所以线程实际上就是一个轻量级的进程。下面给出进程中的线程示意图:


值得注意的是,windos下的线程是有线程控制块(TCB)的。而linux下的进程控制块和线程控制块都是task_struct

为什么称linux下的线程是轻量级进程呢?

这是因为linux内核并没有单独为线程设计一套管理方案,而是通过相同的机制来管理进程和线程,只不过线程拥有的资源是进程的一部分,所以称linux下的线程是轻量级进程。并且,Linux内核中的调度器并不区分线程和进程,可以是单线程的进程,也可以只是一个线程。为了让用户使用起来区分线程和进程,linux向上(用户态)提供了POSI标准的线程接口(如pthread库),在内核用clone系统调用创建和管理线程。尽管有线程这个模型,但底层还是轻量级的进程

总结:==线程是共享同一进程的地址空间和资源的执行单元=。

线程的优点

  1. 共享资源:同一进程内的线程共享地址空间,能访问相同的全局变量,堆和文件描述符等。这种共享使得线程间通信变得更加高效。
  2. 独立的执行流:每个线程都有自己的程序计数器、寄存器和栈,这使得线程可以独立执行。线程的独立性使得多个线程并行执行多个任务,提高了此程序的响应性和吞吐量。
  3. 轻量级:相比于进程,线程的创建开销会小很多,且不需要分配独立的地址空间。上下文切换也比进程快,因为不涉及地址空间的切换
    4.并发执行:在多核处理器上,不同的线程可以做到真正的并行执行

线程的缺点

  1. 同步复杂性:由于共享进程空间,多个线程同时访问和修改共享数据时可能会导致数据不一致等问题
  2. 性能损失:使用锁和其它同步机制会导致性能下降
  3. 调试难度提高:编写和调试一个多线程程序要比单线程程序困难得多

线程异常

  • 单个线程如果出现除0或者访问野指针等问题导致线程崩溃,进程也会随着崩溃
  • 进程终止,该进程的所有线程都会终止。这也就意味着,如果某一个线程出了异常进而终止进程的话,其它的线程也都会被终止。这也是线程不安全的原因之一。

线程和进程

  • 进程是资源分配的基本单位,而线程是调度的基本单位
  • 具体来说,线程共享以下进程资源:
    • 代码段和数据段
    • 文件描述符表
    • 每种信号的处理方式即handler表
    • 环境变量包括当前工作目录
    • 用户id和组id
  • 虽然线程共享进程的数据,但有属于自己的一些数据:
    • 线程ID
    • 一组寄存器
    • errno错误流
    • 信号屏蔽字
    • 调度优先级

进程和线程的关系如下图:
在这里插入图片描述

创建线程

在linux中,通常使用POSIX线程库,即pthread库。pthread库提供了一组用于线程创建、管理和同步的函数,这些函数被包含在pthread.h头文件中。pthread库的主要包含了线程管理、线程同步、线程属性相关的函数,下面介绍线程管理中的一些常用函数。

1.pthread_create

功能:创建一个新的线程
原型:

#include<pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *
(*start_routine)(void*), void *arg);
  • pthread_t是一个无符号整数
  • thread是指向pthread_t变量的一个指针,用于存储创建线程的标识符ID(输出型参数)
  • pthread_attr_t类型是一个线程属性的类,该类定义了线程的所有属性,包括分离状态、栈的大小等
  • attr是一个指向const pthread_attr_t对象的指针,用于初始化被创建线程的属性。如果设置为NULL,则使用默认属性
  • start_rountine是一个函数指针,该函数的参数和返回值类型都是void*。表示线程线程执行的函数
  • arg是传递给线程函数的参数。可以是NULL,如果需要传递多个参数,可以将其打包成结构体类型对象传进去。同样如果想返回多个值,可以将值打包成一个结构体再返回。
  • 创建成功返回0。失败则返回一个非0值,表示错误代码。常见得到错误码有:
    • EAGAIN:系统资源不足,无法创建更多线程。
    • EINVAL:无效的线程属性
    • EPERM:没有足够的权限设置线程属性

给出代码样例,演示使用pthread_create创建线程:

#include <pthread.h>
#include <iostream>
#include <unistd.h>
#include <string.h>using namespace std;void *rout(void *arg)//线程执行函数
{while (true){cout << "i am thread num: " << *(int *)arg << endl;sleep(1);}return NULL;
}int main()
{pthread_t tid;int num = 10;int res = pthread_create(&tid, NULL, rout, (void *)(&num));if (res != 0){//错误码检查fprintf(stderr, "pthread_create: %s\n", strerror(res));exit(1);}while (true){cout << "I am main thread" << endl;sleep(1);}return 0;
}

在这里插入图片描述
这样我们就成功的使用pthread_create函数创建了一个线程。值得注意的是,执行main函数的线程我们称为主线程。此外,一个线程可以使用pthread_self函数来获取自己的线程ID.

2.pthread_self

功能:获得当前线程的ID
函数原型:

pthread_t pthread_self(void);

于是我们可以将前面的代码样例改一下,观察结果线程ID:

#include <pthread.h>
#include <iostream>
#include <unistd.h>
#include <string.h>using namespace std;void *rout(void *arg)
{while (true){cout << "thread id : " << pthread_self() << " i am thread num: " << *(int *)arg << endl;sleep(1);}return NULL;
}int main()
{pthread_t tid;int num = 10;int res = pthread_create(&tid, NULL, rout, (void *)(&num));if (res != 0){fprintf(stderr, "pthread_create: %s\n", strerror(res));exit(1);}while (true){cout << "tid: " << tid << "  I am main thread" << endl;sleep(1);}return 0;
}

在这里插入图片描述
我i们可以观察到,线程ID是一个非常复杂的数字,这个具体数值通常是由线程库内部实现的,可能会使用内存地址等机制来生成唯一的线程ID。

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

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

相关文章

Springboot邮件发送配置

Springboot邮件发送配置 pom.xml依赖&#xff1a; <dependency><groupId>org.eclipse.angus</groupId><artifactId>jakarta.mail</artifactId><version>2.0.3</version> </dependency> <dependency><groupId>or…

跨域的解决方案

1. 计算机更改跨域 1.C盘->Windows->System32->drivers->etc 2.修改hosts 文件2. Chrome浏览器的跨域设置 操作步骤&#xff1a;1.打开我的电脑——C盘 新建一个文件夹&#xff0c;命名为MyChromeDevUserData2.右键——Chrome——快捷方式——目标&#xff0c;在…

ChatGPT成知名度最高生成式AI产品,使用频率却不高

5月29日&#xff0c;牛津大学、路透社新闻研究所联合发布了一份生成式AI&#xff08;AIGC&#xff09;调查报告。 在今年3月28日—4月30日对美国、英国、法国、日本、丹麦和阿根廷的大约12,217人进行了调查&#xff0c;深度调研他们对生成式AI产品的应用情况。 结果显示&…

ElementUI之el-table标题列中显示el-tooltip

ElementUI之el-table标题列中显示el-tooltip 文章目录 ElementUI之el-table标题列中显示el-tooltip1. el-table标题列中显示el-tooltip2. 实现代码3. 展示效果 1. el-table标题列中显示el-tooltip 在el-table-column标签内添加具名插槽v-slot:header 在el-tooltip标签中使用具…

【几何】输入0-360度任意的角度,求上面直线与椭圆相切点的坐标计算公式

输入0-360度任意的角度,求上面直线与椭圆相切点的坐标计算公式 使用积分计算 使用到的公式有椭圆公式: x 2 a 2 + y 2 b 2 = 1 \frac{x^2}{a^2}+\frac{y^2}{b^2} = 1 a2x2​+b2y2​=1 平面旋转公式 X r = cos ⁡ θ ∗ ( X s − X O ) − sin ⁡ θ ∗ ( Y s − Y O ) + X …

端午节粽子龙舟主题互动趣味小游戏效果是什么

端午三天乐&#xff0c;无论节日当天还是之前&#xff0c;行业商家都可以自己的品牌为主借势营销&#xff0c;趣味活动形式玩法和内容呈现达成多种效果&#xff0c;品牌传播、公众号涨粉、线下互动、商品促销、用户促活等。 在【雨科】平台拥有多款端午节互动小游戏类型&#…

网易狼人杀 设置点击自动发言

我们玩网易狼人杀 刚开始 都会发现 要按住麦克风才能发言 不得不说 相当的麻烦 我们可以点击如下图 右上角这个设置的齿轮 新弹出的设置面板上 勾选这个点击发言 然后 我们只需要 点一下 就可以进入发言状态 然后 再点一下即可停止发言 会方便非常多

zabbix事件告警监控:如何实现对相同部件触发器告警及恢复的强关联

有一定Zabbix使用经验的小伙伴可能会发现&#xff0c;接收告警事件时&#xff0c;其中可能包含着大量不同的部件名&#xff0c;同一部件的事件在逻辑上具有很强关联性&#xff0c;理论上应保持一致的告警/恢复状态&#xff0c;但Zabbix默认并未对它们进行关联&#xff0c;直接后…

AIGC降重:如何2分钟降低论文AI率和查重率?推荐使用SpeedAI科研小助手

确保学术论文的独立性与诚信性&#xff0c;对于学业的成就及学位的获取至关重要&#xff0c;其中&#xff0c;论文的人工智能查重与降低AIGC相似度扮演着核心角色。 常规的查重手段主要围绕查重软件的运用和个体的自行审查&#xff1b;而降重则通常通过语句重组、同义替换、内…

单细胞分析(Signac): PBMC scATAC-seq 基因组区域可视化

引言 在本教学指南中&#xff0c;我们将探讨由10x Genomics公司提供的人类外周血单核细胞&#xff08;PBMCs&#xff09;的单细胞ATAC-seq数据集。 加载包 首先加载 Signac、Seurat 和我们将用于分析人类数据的其他一些包。 if (!requireNamespace("EnsDb.Hsapiens.v75&qu…

ModuleNotFoundError: No module named ‘osgeo‘

显示无osgeo模块 pip install osgeo显示失败 方法&#xff1a; 确保你已经安装了正确的依赖项&#xff0c;例如GDAL、GEOS和PROJ等。 方法1&#xff1a;pip install gdal 失败 方法2&#xff1a;官网下载失败&#xff0c;下载地址&#xff1a;https://www.lfd.uci.edu/~gohl…

设置自动刷新数据透视表的数据源

数据透视表数据源的自动刷新 一般情况操作&#xff1a; 自动刷新操作&#xff1a; 1、定义名称名称 引用位置&#xff1a;OFFSET(Sheet1!$A$1,0,0,COUNTA(Sheet1!$A:$A),COUNTA(Sheet1!$1:$1)) 2、数据透视表的数据源更改为【源数据】—— 即前面定义的名称 3、数据——全部…

区块链技术和应用二

前言 学习长安链的一些基本原理 官网&#xff1a;长安链开源文档 b站课程&#xff1a;区块链基础与应用 一、共识算法 1.1 POW工作量证明 最长链共识&#xff0c;没听明白 1.2 51%攻击 二、区块链的发展 2.1 区块链1.0到3.0 2.2 共有链、联盟链、私有链 2.3 发展趋势 2.4 扩…

CUDA_VISIBLE_DEVICES‘ 不是内部或外部命令,也不是可运行的程序或批处理文件。

问题&#xff1a; 命令行出现CUDA_VISIBLE_DEVICES0 python trainer.py这种命令 这是Linux可以的&#xff0c;但是Windows不行。 解决方案&#xff1a; 这条命令的含义是指定某个GPU来运行程序&#xff0c;我们可以在程序开头添加指定GPU的代码&#xff0c;效果是一样的&…

HackTheBox-Machines--Lazy

Lazy测试过程 1 信息收集 1.端口扫描 发现 SSH&#xff08;22&#xff09;、HTTP&#xff08;80&#xff09;端口 nmap -sC -sV 10.129.159.512.访问 80 端口 1.页面中存在注册功能&#xff0c;测试注册功能 页面返回登录页面及用户名 使用burpsuite观察注册请求 /register.p…

Facebook:连接世界,畅游社交之旅

作为全球最大的社交平台之一&#xff0c;Facebook不仅仅是一个网站&#xff0c;更是一个连接世界的桥梁&#xff0c;让人们可以轻松地与全球各地的朋友、家人和同事保持联系&#xff0c;分享生活、交流想法&#xff0c;畅游社交的无边界之旅。本文将带领读者探索Facebook的魅力…

电子商务网站(网上商店PetShop)

PetShop是一个范例&#xff0c;微软用它来展示.Net企业系统开发的能力。PetShop随着版本的不断更新&#xff0c;至现在基于.Net2.0的PetShop 4.0为止&#xff0c;整个设计逐渐变得成熟而优雅&#xff0c;有很多可以借鉴之处。PetShop是一个小型的项目&#xff0c;系统架构与代码…

鸿蒙OS开发:【一次开发,多端部署】(分栏控件)

一多分栏控件 介绍 本示例分别展示了多场景下&#xff0c;一多分栏控件的响应式变化效果。 本示例分别用到了[SideBarContainer]组件与[Navigation]组件&#xff0c;对应使用场景如下&#xff1a; ABC&#xff1a;即SideBarContainer组件组合Navigation组件AC&#xff1a;S…

NI PXIe-7857R与PXIe-8842的区别

一、NI PXIe-7857R 类型&#xff1a; FPGA模块&#xff1a;基于FPGA的可编程I/O模块。 主要功能&#xff1a; FPGA处理&#xff1a;包含Xilinx Kintex-7 FPGA&#xff0c;支持自定义逻辑和处理。 I/O接口&#xff1a;提供丰富的模拟和数字I/O通道。 高速数据处理&#xff1a…

软件测试新手要达到一个什么水平才能找到一份9K的工作?

我的读者里有很多 软测 新人&#xff0c;新人是指正在学 测试 的、以及工作时间不长的年轻人&#xff0c;他们经常问我一个问题&#xff1a; 自学到什么程度才能找到一份还不错的测试工作&#xff1f; 今天我就从我自己面试新人的角度来回答一下&#xff0c;我会把面试的知识点…