[Linux]多线程详解

多线程

  • 1.线程的概念和理解
    • 1.1线程的优点
    • 1.2线程的缺点
    • 1.3线程的设计
    • 1.4线程 VS 进程
  • 2.线程控制
    • 2.1线程等待
    • 2.2 线程终止
    • 2.3 线程分离
  • 3.线程互斥
    • 3.1背景
    • 3.2抢票代码演示
    • 3.3保护公共资源(加锁)
      • 3.3.1创建锁/销毁锁
      • 3.3.2申请锁/尝试申请锁/解锁
    • 3.4解决抢票的出错逻辑
    • 3.5 理解锁
  • 4.线程同步(条件变量)

1.线程的概念和理解

在一个程序中的一个执行路线就是线程,更官方的定义就是线程是一个进程内部的控制序列

单线程中代码都是串行调用的。
我们想要实现并发调用也可以使用创建多进程的方法,但是创建进程是比较消耗资源的,要创建进程结构,页表,并建立映射关系,成本比较高;
但是线程就不一样了,在地址空间内创建的“进程”就叫做线程,只需要创建内核数据结构即可。

线程:就是进程内部的一个执行分支

1.1线程的优点

在这里插入图片描述

1.2线程的缺点

在这里插入图片描述

1.3线程的设计

线程也是要被管理的,进程有PCB,线程也有类似的东西(TCB)
在这里插入图片描述
但是这样创建非常的复杂,线程和进程有高度的相似性,没有必要单独设计这个算法,所以使用进程来模拟线程

1.4线程 VS 进程

在这里插入图片描述
从内核的角度出发,进程就是承担分配系统资源的基本实体。

那么多执行流是如何进行代码划分的?

在这里插入图片描述
一个32位分成了3个部分大小分别为10 10 12
前10个是页目录
中间10个是页表
在这里插入图片描述
页表如何找到相应的内存中的数据?
页表中的地址+ 虚拟地址后12位对应的数据(页内偏移)

给线程分配不同的区域,本质是就是给不同的线程,各自看到全部页表的子集

在这里插入图片描述

在这里插入图片描述

2.线程控制

linux中没有真线程,只有轻量级进程的概念,但是用户只认线程
所以linux中没有线程相关的系统调用,只有轻量级进程的系统调用,
pthread库—原生线程库——>将轻量级进程的系统调用进行封装,转换成线程相关的接口提供给用户。
所以我们在编写线程代码时必须 -pthread
在这里插入图片描述
线程演示代码:

void *threadrun(void *arg)
{int cnt = 5;while (cnt){cout << "新线程正在运行:" << cnt << "pid:" << getpid() << endl;sleep(1);cnt--;}return nullptr;
}
int main()
{// int pthread_create(pthread_t * thread, const pthread_attr_t *attr,// void *(*start_routine)(void *), void *arg);pthread_t tid;pthread_create(&tid, nullptr, threadrun, nullptr);int cnt = 10;while (cnt){cout << "主线程正在运行:" << cnt << "pid:" << getpid() << endl;sleep(1);cnt--;}return 0;
}

在这里插入图片描述
可以看出两个循环是一起运行的,所以进程中是有两个执行流的,并且他们是属于同一个进程。
主线程退出==进程退出,所有线程都要结束运行退出。

  1. 一般来说为了保证线程完成我们预期的工作,都是要保证主线程最后结束
  2. 线程也是需要被等待的,不然就会产生类似于进程退出的内存泄漏问题。
    补充:

ps -aL :会列出系统中所有具有终端的进程以及线程

2.1线程等待

在这里插入图片描述
void *retval:输出型参数,他就是线程的返回值(返回值为void)类型的

2.2 线程终止

同一个进程内,大部分资源都是共享的,其中就包括了地址空间。

线程出异常:
多线程中任何一个线程出现了异常,都会导致整个进程退出。

  1. 一个线程出问题,导致其他线程也出现问题,导致整个进程退出----线程安全问题
  2. 多线程中,公共函数被多个线程同时进入—出现重入问题

线程退出的时候不会像进程退出一样拿到退出信息,因为一但线程出异常之后,整个进程都会退出,没有时间来进行线程等待。
注意:线程退出不可以使用exit,这样会导致整个进程退出。

线程退出的三种方式

  1. return
  2. pthread_exit在这里插入图片描述
  3. pthread_cancel:取消线程(让主线程去取消目标线程)在这里插入图片描述

2.3 线程分离

默认情况下线程也是要被等待的,但是线程也是可以手动设置分离的。
如果主线程不关系新线程的执行结果,我们可以把新线程设置为分离状态。
在这里插入图片描述
被分离之后的线程就不可以再join了,不然就会出错。

线程分离:底层依旧是一个进程,一般都希望主线程最后一个退出,所以在线程分离中,主线程一般都是永远不退出的。

3.线程互斥

3.1背景

多个执行流共享的资源是共享资源,但是我们把他保护起来,一次只允许一个线程访问,这个就叫做临界资源
在代码中,访问临界资源的代码就叫做临界区

互斥:任何时刻,只允许一个执行流进入临界区,访问临界资源。
原子性:不会被任何调度机制大端,只有两种形态,要么完成,要么未完成。

3.2抢票代码演示

在这里插入图片描述
在这里插入图片描述
tickets>0;这是一个逻辑运算,当处理时,cpu会把内存中的数据拷贝到寄存器中,但是当进行到usleep时,这个线程就会进入等待队列,并且带走自己的上下文数据,没有执行到tickets–的位置,就会导致判断失误,会有很多的线程进入到这个抢票逻辑中取。

当进入到–操作时,把数据从内存读取到cpu,cpu进行内部–,再重新写回内存。

我们再从编译的角度去理解原子性
如果一个代码转换成汇编只有一条语句那他就是原子的
例如 - -操作,就不是原子,他会被转化为3条语句
在这里插入图片描述

3.3保护公共资源(加锁)

3.3.1创建锁/销毁锁

在这里插入图片描述
如果定义的锁是静态的或者是全局的,就不需要初始化也不需要销毁
直接:

pthread_mutex_tmutex=PTHREAD_MUTEX_INITIALIZER;

3.3.2申请锁/尝试申请锁/解锁

在这里插入图片描述申请锁/尝试申请锁,区别就是申请锁出错会阻塞,而另一个出错直接返回。

3.4解决抢票的出错逻辑

出现并发访问的问题,本质就是因为多个执行流并发访问全局数据的代码导致的,保护共享资源本质就是保护临界区
在这里插入图片描述
加锁的本质就是把并发访问的代码,变成串行访问,并且加锁的粒度要越细越好。

在这里插入图片描述
在这里插入图片描述
注意:有些平台会出现上面的问题,加锁之后,不同线程对锁的竞争强度不同,这算是一个bug,原则上竞争锁是自由的,竞争锁的能力太强就会导致饥饿问题。

3.5 理解锁

在这里插入图片描述

4.线程同步(条件变量)

一个线程跑完就接着下一个,解决饥饿问题。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

pthread_cond_t cond=PTHREAD_COND_INITIALIZER;

条件变量是在加锁内使用的。
从条件变量的函数来看,其实他和锁的用法极其的相似。

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

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

相关文章

大学语文教材电子版(第十一版)教学用书PDF及课件

大学语文课件&#xff1a;https://caiyun.139.com/m/i?005CiDusEVWnR 《大学语文》&#xff08;第十一版&#xff09;主编&#xff1a;徐中玉 齐森华 谭帆。 大学语文教材电子版教师用书PDF第一课《齐桓晋文之事》艺术赏析&#xff1a; 孟子四处游说&#xff0c;养成善辩的…

MySQL【七】

字符串函数 数学函数 日期函数 条件控制函数 类型转换函数 系统信息函数 自定义函数 DELIMITER  CREATE FUNCTION 函数名([参数名 参数数据类型[,…]])RETURNS 函数返回值的数据类型BEGIN函数体;RETURN 语句;ENDDELIMITER ;sql ########## 定义一个函数maxofthree()&#x…

第三百二十三节 Java线程教程 - Java同步器

Java线程教程 - Java同步器 同步器对象与一组线程一起使用。 它维护一个状态&#xff0c;根据它的状态&#xff0c;它让一个线程通过或强迫它等待。 本节将讨论四种类型的同步器&#xff1a; SemaphoresBarriersLatchesExchangers 信号量 信号量用于控制可以访问资源的线程…

《Java核心技术 卷I》用户界面AWT事件继承层次

AWT事件继承层次 EventObject类有一个子类AWTEvent&#xff0c;它是所有AWT事件类的父类。 Swing组件会生成更多其他事件对象&#xff0c;都直接拓展自EventObject而不是AWTEvent。 AWT将事件分为底层(low-level)事件和语义事件。 语义事件&#xff1a;表示用户的动作事件&…

Ubuntu从入门到精通(一)系统安装

Ubuntu从入门到精通&#xff08;一&#xff09; 1 Ubuntu镜像选择 下载Ubuntu 20.04系统ISO镜像 安装 Ubuntu 20.04系统,就必须有 Ubuntu 20.04系统软件安装程序可以通过浏览器访问Ubuntu20.04的官方站点&#xff0c; 然后在导舰栏找划 Dowwnloads->Mirrors链接&#xff…

用户自定义IP核——ZYNQ学习笔记6

一、试验任务 通过自定义一个 LED IP 核&#xff0c;通过 PS 端的程序来控制底板上 PL 端 LED1 呈现呼吸 灯的效果&#xff0c;并且 PS 可以通过 AXI 接口来控制呼吸灯的开关和呼吸的频率。 二、创建IP核 三、创建工程&#xff0c;调用IP #include "stdio.h" #includ…

Elasticsearch 8.16.0:革新大数据搜索的新利器

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/literature?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;…

python:用 sklearn 构建 K-Means 聚类模型

pip install scikit-learn 或者 直接用 Anaconda3 sklearn 提供了 preprocessing 数据预处理模块、cluster 聚类模型、manifold.TSNE 数据降维模块。 编写 test_sklearn_3.py 如下 # -*- coding: utf-8 -*- """ 使用 sklearn 构建 K-Means 聚类模型 "&…

【大数据学习 | HBASE高级】hive操作hbase

一般在查询hbase的数据的时候我们可以直接使用hbase的命令行或者是api进行查询就行了&#xff0c;但是在日常的计算过程中我们一般都不是为了查询&#xff0c;都是在查询的基础上进行二次计算&#xff0c;所以使用hbase的命令是没有办法进行数据计算的&#xff0c;并且对于hbas…

贴代码框架PasteForm特性介绍之markdown和richtext

简介 PasteForm是贴代码推出的 “新一代CRUD” &#xff0c;基于ABPvNext&#xff0c;目的是通过对Dto的特性的标注&#xff0c;从而实现管理端的统一UI&#xff0c;借助于配套的PasteBuilder代码生成器&#xff0c;你可以快速的为自己的项目构建后台管理端&#xff01;目前管…

ServletConfig、ServletContext、HttpServletRequest与HttpServletResponse常见API

目录 一、ServletConfig 二、ServletContext 三、ServletContext其他重要API (一)获取文件路径和上下文 (二)域对象的相关API 四、HttpServletRequest常见API (一)获取请求行/头信息相关 (二)获得请求参数相关 五、HttpServletResponse常见API 一、ServletConfig Se…

MySQL缓存使用率超过80%的解决方法

MySQL缓存使用率超过80%的解决方法 一、识别缓存使用率过高的问题1.1 使用SHOW GLOBAL STATUS命令监控1.2 监控其他相关指标二、分析缓存使用率过高的原因2.1 数据量增长2.2 查询模式变化2.3 配置不当三、解决缓存使用率过高的方法3.1 调整Buffer Pool大小3.1.1 计算合理的Buff…

新手教学系列——善用 VSCode 工作区,让开发更高效

引言 作为一名开发者,你是否曾经在项目中频繁地切换不同文件夹,打开无数个 VSCode 窗口?特别是当你同时参与多个项目或者处理多个模块时,这种情况更是家常便饭。很快,你的任务栏上挤满了 VSCode 的小图标,切换起来手忙脚乱,工作效率直线下降。这时候,你可能会问:“有…

springboot004基于springboot004网页时装购物系统(源码+包运行+LW+技术指导)

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下&#xff0c;你想解决的问…

丹摩征文活动 |【前端开发】HTML+CSS+JavaScript前端三剑客的基础知识体系了解

前言 &#x1f31f;&#x1f31f;本期讲解关于HTMLCSSJavaScript的基础知识&#xff0c;小编带领大家简单过一遍~~~ &#x1f308;感兴趣的小伙伴看一看小编主页&#xff1a;GGBondlctrl-CSDN博客 &#x1f525; 你的点赞就是小编不断更新的最大动力 …

进程信号

目录 信号入门 1. 生活角度的信号 2. 技术应用角度的信号 3. 注意 4. 信号概念 5. 用kill -l命令可以察看系统定义的信号列表 6. 信号处理常见方式概览 产生信号 1. 通过终端按键产生信号 Core Dump 2. 调用系统函数向进程发信号 3. 由软件条件产生信号 4. 硬件异…

【链路层】空口数据包详解(4):数据物理通道协议数据单元(PDU)

目录 一、概述 1.1. 头部&#xff08;Header&#xff09;结构 1.2. MIC字段的情况说明 1.3. 有效载荷&#xff08;Payload&#xff09;格式与LLID字段的关联 二、LL Data PDU 2.1. 定义与用途 2.2. 头部字段设置 2.3. 空PDU&#xff08;Empty PDU &#xff09; 2.4. 数…

使用 Web Search 插件扩展 GitHub Copilot 问答

GitHub Copilot 是一个由 GitHub 和 OpenAI 合作开发的人工智能代码提示工具。它可以根据上下文提示代码&#xff0c;还可以回答各种技术相关的问题。但是 Copilot 本身不能回答非技术类型的问题。为了扩展 Copilot 的功能&#xff0c;微软发布了一个名为 Web Search 的插件&am…

24 年第十届数维杯国际数模竞赛赛题浅析

本次万众瞩目的数维杯国际大学生数学建模赛题已正式出炉&#xff0c;无论是赛题难度还是认可度&#xff0c;该比赛都是数模届的独一档&#xff0c;含金量极高&#xff0c;可以用于综测加分、保研、简历添彩等各方面。考虑到大家解题实属不易&#xff0c;为了帮助大家取得好成绩…

无人机检测车辆——多目标检测

目录 YOLOv3&#xff08;You Only Look Once version 3&#xff09;简介 YOLOv3 的主要特点 YOLOv3 的结构 1. 特征提取网络&#xff08;Backbone&#xff09; 2. 检测头&#xff08;Head&#xff09; 3. 输出层 YOLOv3 损失函数 YOLOv3 的优势 YOLOv3 的应用 YOLOv3…