【Linux 线程介绍】

news2025/1/11 22:45:24

Linux 线程

  • 线程一定越多越好吗?
  • 线程的实现方式:
  • API:
  • pthread_exit函数演示
  • 获取线程的返回值
  • 多线程的不安全性
  • 查看进程中的线程数

进程:一个正在运行的程序 ,资源分配的基本单位
线程:进程内部的一条执行序列(路径) 调度的基本单位

线程一定越多越好吗?

首先,我们要明白线程也是需要资源的。

  • 线程的创建和销毁需要花费资源 (陷入内核) 线程栈本身需要占用空间
  • 线程之间上下文切换的适合需要把CPU和寄存器中的数据压到栈中,切换回之后又得恢复
  • 大量线程同时唤醒会使系统经常出现锯齿负载或者瞬间量很大导致宕机
  • 唤醒线程也需要资源

由上面可以看出,线程并不是越多越好,我们什么时候应该使用多线程?

首先我们先了解一下。

程序一般分为两类

  1. IO密集型 (会阻塞)程序涉及一些IO操作,文件操作,网络操作。
  2. CPU密集型 程序大多数都在做运算的

对于多核的主机来说:

CPU密集型的程序:适合设计为多线程,把任务拆分,可以更快

IO密集型的程序:适合设计为多线程,因为如果一些IO没有准备好,系统则会把它放到阻塞队列中,这个时候会把它的时间片给就绪队列中的任务

对于单核主机来说:

IO密集型的程序:适合设计为多线程,当等待IO资源时,便会把时间片让给其它任务

CPU密集型的程序:不合适设计为多线程,单核和多核计算的时间是一样的,但是如果是多线程的话,线程切换会耗费大量的资源和时间

在上面的情况下,我们创建线程的数目一般为主机的核数,如果业务中IO操作比较多的话,那么线程数目也可以稍微多于核数

线程的实现方式:

用户级线程(多个用户线程对应一个内核线程)
在这里插入图片描述
以创建很多数目的线程,这个线程的创建是由线程库中的代码来创建,内核并不参与。
优点 :开销小,
缺点 :无法真正的利用多个处理器,因为内核无法感知到线程的存在,所以这些线程无法被调度的空闲的处理器上去运行

内核级线程(每个用户线程都对应一个内核线程)
在这里插入图片描述
每个线程是由内核创建的
优点 :可以利用多个处理器,可以实现真正意义上的并行,用户级的只能是并发
缺点: 创建开销大

组合级线程(每个用户线程对应不同数量的内核线程)
在这里插入图片描述
组合级则是它俩的组合

在Linux系统上,对于内核来说,没有线程这个概念,它视为这是一个轻量级的进程,线程被内核视为与其他进程共享资源的进程,直接给它一个PCB,也会消耗一个PID,只不过叫线程id,与它的主线程共享进程空间,共享打开的文件资源等等。

API:

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine)(void *), void *arg);创建线程
thread:指向线程的指针
attr:指定线程的属性
start_coutine:线程函数
arg:传递给线程函数的参数
返回值:成功返回0,失败返回错误码
int pthread_exit(void *retval);终止当前线程,只会终止当前线程,不会影响进程中其它线程的执行。
retval:指定退出信息
int pthread_join(pthread_t thread, void **retval);等待thread指定的线程退出,线程未退出时,该方法阻塞
retval:接收 thread线程退出时,指定的退出信息

pthread_exit函数演示

#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
void * fun(void * arg)
{
 for(int i=0;i<5;++i)
 {
  printf("fun \n");
 
 }
}
int main()
{
 pthread_t id;
 pthread_create(&id,NULL,fun,NULL);
 for(int i=0;i<5;++i)
 {
  printf("main \n");
 
 }
 exit(0);
}

执行结果
在这里插入图片描述

#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
void * fun(void * arg)
{
 for(int i=0;i<5;++i)
 {
  printf("fun \n");
 
 }
}
int main()
{
 pthread_t id;
 pthread_create(&id,NULL,fun,NULL);
 for(int i=0;i<5;++i)
 {
  printf("main \n");
 
 }
 pthread_exit(NULL);
}

执行结果
在这里插入图片描述
因为在我们上面代码,执行exit(0)的时候,会把整个进程都终止掉,同时也会把我们创建的线程的资源释放,而当我们使用pthread_exit时,只会把主线程终止掉,而不会影响到我们创建的那个线程。

在这里插入图片描述

获取线程的返回值

#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
void * fun(void * arg)
{
 for(int i=0;i<5;++i)
 {
  printf("fun \n");
 
 }
 pthread_exit("fun over");
}
int main()
{
 pthread_t id;
 pthread_create(&id,NULL,fun,NULL);
 for(int i=0;i<5;++i)
 {
  printf("main \n");
 
 }
 char * s;
 pthread_join(id,(void **)&s);
 printf("s=%s",s);
 exit(0);
}

在这里插入图片描述

多线程的不安全性

5个线程同时对一个全局变量加1000

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
int index =0;
void * fun(void *arg)
{
  for(int i=0;i<1000;++i)
  {
   printf("index =%d\n",index++);
  
  }

}
int main()
{
 pthread_t arid[5]={0};
 for(int i=0;i<5;++i)
 {
  pthread_create(&arid[i],NULL,fun,NULL);

 }
 for(int i=0;i<5;++i)
 {
   pthread_join(arid[i],NULL);
 
 }
  exit(0);

}

在这里插入图片描述

最后的结果为4998,而不是5000,这个是为什么,++这个操作并不是原子操作。
我的这个虚拟机是2核的,比如说此时i值为2,当一个线程刚对i值进行i++操作后,此时i值变成3,正要写回,而此时可能时间片到了,然后其它线程进行执行,然后这个线程此时读到i的值为2(因为没有写回),对其加1,然后写回,当时间片又轮到上面的线程时,此时它又按照上面的步骤进行执行,恢复现场,此时寄存器中保存的i值为3,又进行写回,此时i值还为3。
本来经过2次加操作,i的值应该为4,而此时为3。

查看进程中的线程数

需要添加L(小写不行)
![在这里插入图片描述](https://img-blog.csdnimg.cn/70be25076d1c445496fe40d9d68fedcd.pn
线程号是以进程的id号递增的

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

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

相关文章

接口自动化测试

接口自动化测试1.基础知识1.接口测试原理2.接口测试点及用例设计方法3.接口测试返回值的处理4.接口测试要点5.常见HTTP状态码6.HTTP基础知识7.接口自动化测试工具2.抓包工具1.chrom抓包2.Fiddle抓包&#xff08;PC端&#xff0c;手机端&#xff09;1.原理2.下载安装3. 认识界面…

HIbernate多表学习

一&#xff0c;表与表之间关系&#xff1a; 1.一对多&#xff1a;多的表用一个外键存一的表的主键id。 2.多对多&#xff1a;新建第三张表&#xff0c;两个外键分别存两个多的表的主键id。 3.一对一 二&#xff0c;Hibernate一对多练习&#xff1a; 一对多映射配置&#…

国际通用回收标准-GRS、RCS的答疑

【国际通用回收标准-GRS、RCS的答疑】 GRS & RCS 国际通用回收标准 GRS和 RCS是目前现行国际公认的回收材料标准。许多国际知名品牌如 ADDIDAS、3M、PUMA、H&M、NIKE等都是此标准的会员。GRS与 RCS最早开始于纺织产业&#xff0c;用以证明其产品或原料含有一定的回收材…

yolov5剪枝实战4: 正常训练和稀疏化训练

1. 准备自己的数据集 1.1 下载项目文件 准备好备注的数据集进行训练,我这里给出了标注好的足球的数据集。从百度网盘下载到项目目录下并解压,网盘地址见文末 VOCdevkit_ball.ziptestfiles.zipprepare_data.py1.2 解压建立或自行建立数据集 使用PASCAL VOC数据集的目录结构,…

怎么批量把图片转文字?教你几招轻松完成

工作中我们经常要与图片、文字打交道&#xff0c;特别是做资料收集的小伙伴&#xff0c;当收到图片资料的时候&#xff0c;就需要将其输出为文字进行保存&#xff0c;如果是单张的时候我们还可以使用手机或者微信直接拍照识别转&#xff0c;但是图片不止一张的时候&#xff0c;…

nvcc编译器之GPU代码编译(chapter 5)

目录 5. GPU编译 5.1 GPU多代架构 5.2 GPU特性列表 5.3 应用兼容性 5.4 虚拟架构 5.5 虚拟架构特性列表 5.6 兼容性补全机制 5.7 nvcc示例 5. GPU编译 本章描述了由nvcc与CUDA驱动协同维护的GPU编译模型。本文介绍了一些技术部分&#xff0c;并在最后给出了具体的示例…

100家!第一批5G应用解决方案供应商推荐名录

近日&#xff0c;5G应用产业方阵&#xff08;5G AIA&#xff09;在“2022年中国5G发展大会5G应用产业发展论坛”发布了“5G应用解决方案供应商推荐名录&#xff08;第一批&#xff09;”入库名单&#xff0c;旨在强化5G应用供需对接&#xff0c;推动5G应用解决方案成熟&#xf…

RDD缓存机制及持久化技术

文章目录RDD缓存RDD缓存API介绍RDD缓存代码演示示例RDD缓存执行原理RDD CheckPointCheckPoint代码演示示例CheckPoint与Cache对比RDD缓存 RDD之间进行Transformation计算&#xff0c;当执行开启之后&#xff0c;就会有新的RDD生成&#xff0c;而之前老的RDD就会消失&#xff0…

js逆向基础篇-某音乐网站-xx音乐

提示!本文章仅供学习交流,严禁用于任何商业和非法用途,如有侵权,可联系本文作者删除! 网站链接:aHR0cHM6Ly9tdXNpYy4xNjMuY29tLyMvc2VhcmNoL20vP3M9JUU1JUE0JUE5JUU0JUI4JThCJnR5cGU9MQ== 案例分析: 搜索歌曲名称,找到列表接口,如上图能看到列表数据的,之后看下传参,…

249 h221 最大岛屿面积

方式1 错误的动态规划 递归公式为 if (matrix[i][j]‘1’&&matrix[i-1][j-1]‘1’){ int edge(int) Math.pow(dp[i][j],0.5); // 边长 int addCount addCount(matrix, i, j, edge); dp[i][j]dp[i-1][j-1]addCount; maxMath.max(max,dp[i][j]); } 只根据 dp[i-1][j-1]…

Dev C++开发环境的配置及使用

标题Dev C开发环境的配置及使用 本文引用自作者编写的下述图书; 本文允许以个人学习、教学等目的引用、讲授或转载&#xff0c;但需要注明原作者"海洋饼干叔 叔"&#xff1b;本文不允许以纸质及电子出版为目的进行抄摘或改编。 1.《Python编程基础及应用》&#xff0…

免费题库接口

免费题库接口 本平台优点&#xff1a; 多题库查题、独立后台、响应速度快、全网平台可查、功能最全&#xff01; 1.想要给自己的公众号获得查题接口&#xff0c;只需要两步&#xff01; 2.题库&#xff1a; 查题校园题库&#xff1a;查题校园题库后台&#xff08;点击跳转&a…

[SUCTF 2019]Pythonginx

源码&#xff1a; app.route(/getUrl, methods[GET, POST]) def getUrl():url request.args.get("url")host parse.urlparse(url).hostnameif host suctf.cc:return "我扌 your problem? 111"parts list(urlsplit(url))host parts[1]if host suctf…

[论文评析]Densely Connected Convolutional Networks,CVPR,2017

Densely Connected Convolutional Networks&#xff0c; 文章信息背景与动机DenseNetDense blockDenseNetDenseNet的集中经典配置总结文章信息 题目&#xff1a;Densely Connected Convolutional Networks&#xff0c; 发表&#xff1a;CVPR,2017 作者&#xff1a;Gao Huang, …

【TWVRP】遗传算法求解带时间窗的含充电站车辆路径规划问题【含Matlab源码 1177期】

⛄一、VRP简介 1 VRP基本原理 车辆路径规划问题(Vehicle Routing Problem&#xff0c;VRP)是运筹学里重要的研究问题之一。VRP关注有一个供货商与K个销售点的路径规划的情况&#xff0c;可以简述为&#xff1a;对一系列发货点和收货点&#xff0c;组织调用一定的车辆&#xff…

【密码学篇】虚拟专用网技术原理与应用(商密)

【密码学篇】虚拟专用网技术原理与应用&#xff08;商密&#xff09; VPN技术不是洪水猛兽&#xff0c;其普遍应用于网络通信安全和网络接入控制&#xff0c;可通过服务器、硬件、软件等多种方式实现。—【蘇小沐】 文章目录【密码学篇】虚拟专用网技术原理与应用&#xff08;…

JAVA多线程并发(一):线程的创建

JAVA多线程并发——创建线程 第一章&#xff1a;线程的创建与实现 文章目录JAVA多线程并发——创建线程一、继承Thread类二、实现runnable接口三、简单匿名内部类写法四、实现Callable接口五、线程池一、继承Thread类 代码示例&#xff1a; public class ExtendThread {publ…

SPARKSQL3.0-Unresolved[Parsed]阶段源码剖析

一、前言 上两节介绍了Antlr4的简单使用以及spark中如何构建SessionState&#xff0c;如果没有看过建议先了解上两节的使用&#xff0c;否则看本节会比较吃力 [SPARKSQL3.0-Antlr4由浅入深&SparkSQL语法解析] [SPARKSQL3.0-SessionState构建源码剖析] 那么在Unresolved…

MySql查询的生命周期和性能优化思路

目录 前言 1. 为什么查询性能差 2. 一次查询的生命周期 2.1 客户端与服务端通信 2.2 查询缓存 2.3 解析器 2.4 预处理器 2.5 优化器 2.6 查询引擎 2.7 存储引擎 3. 查询性能优化的思路 4.总结 前言 一说到mysql的查询性能优化&#xff0c;相信很多人能说出来很多的技…

AT32F407/437使用FreeRTOS并实现ping客户端

示例目的 基于以太网络&#xff0c;实现ping客户端已检测网络联机。 支持型号 AT32F407xx AT32F437xx 主要使用外设 EMAC GPIO USART 快速使用方法硬件资源 1) 指示灯LED2/LED3 2) USART1(PA9/PA10) 3) AT-START-F407/ AT-START-F437实验板 4) 以太网连接线软件资源 1) SourceC…