[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;

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

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

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

相关文章

CSP-J 2024题解

省流&#xff1a;300->260 乐。 Poker: 我考场上寻思着会不会有人写成了 joker.in joker.out&#xff0c;结果真的有 joker Sol EZ problem&#xff0c;拿 set 搞一下就行了&#xff08;虽然我赛事没想到&#xff0c;用了 map&#xff09; Code #include <bits/std…

【miniMax开放平台-注册安全分析报告-无验证方式导致安全隐患】

前言 由于网站注册入口容易被机器执行自动化程序攻击&#xff0c;存在如下风险&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露&#xff0c;不符合国家等级保护的要求。短信盗刷带来的拒绝服务风险 &#xff0c;造成用户无法登陆、注册&#xff0c;大量收到垃圾短信的…

python机器人Agent编程——多Agent框架的底层逻辑(上)

目录 一、前言二、两个核心概念2.1 Routines&#xff08;1&#xff09;清晰的Prompt&#xff08;2&#xff09;工具调用json schema自动生成&#xff08;3&#xff09;解析模型的toolcall指令&#xff08;4&#xff09;单Agent的循环决策与输出 PS.扩展阅读ps1.六自由度机器人相…

达梦 DG

监视器 switchover 关于达梦DG switchover的细节&#xff0c;以下是一些关键步骤和注意事项&#xff1a; • 切换前检查确认&#xff1a; • 确认数据库版本和DG架构&#xff0c;包括IP信息及切换角色前后的情况。 • 检查DG切换方式&#xff0c;是switch over还是fail ove…

blind-watermark - 水印绑定

文章目录 一、关于 blind-watermark安装 二、bash 中使用三、Python 调用1、基本使用2、attacks on Watermarked Image3、embed images4、embed array of bits 四、并发五、相关 Project 一、关于 blind-watermark Blind watermark 基于 DWT-DCT-SVD. github : https://githu…

从零开始的c++之旅——二叉搜索树

1、二叉搜索树概念 1. ⼆叉搜索树的概念 ⼆叉搜索树⼜称⼆叉排序树&#xff0c;它或者是⼀棵空树&#xff0c;或者是具有以下性质的⼆叉树: • 若它的左⼦树不为空&#xff0c;则左⼦树上所有结点的值都⼩于等于根结点的值 • 若它的右⼦树不为空&#xff0c;则右⼦树上所有结…

类与对象;

目录 一、认识类&#xff1b; 1、类的引入&#xff1b; 2、类的定义&#xff1b; 类的两种定义方式&#xff1a; 3、类的访问限定符及封装&#xff1b; 4、类的作用域&#xff1b; 5、类的实例化&#xff1b; 6、类对象模型&#xff1b; 计算类对象的大小&#xff1b; …

ceph的集群管理

0 环境说明 ip地址主机名额外硬盘是否加入ceph集群10.0.0.141ceph141sdb 300G&#xff0c;sdc 500G是10.0.0.142ceph142sdb 300G&#xff0c;sdc 500G, sdd 1000G否10.0.0.143ceph143sdb 300G&#xff0c;sdc 500G否 在上一篇文章中&#xff0c;已经成功地初始化了一个ceph管…

企业无线解决方案

前言 无线广域网 无线广域网WWAN&#xff08;Wireless Wide Area Network&#xff09;目前已经成为了全球通信系统的核心组成部分&#xff0c;我们所熟悉的2G网络、3G网络和4G网络&#xff08;LTE&#xff09;等等都是WWAN的典型代表。通过WWAN&#xff0c;用户几乎可以在任何…

Springboot集成ElasticSearch实现minio文件内容全文检索

一、docker安装Elasticsearch &#xff08;1&#xff09;springboot和Elasticsearch的版本对应关系如下&#xff0c;请看版本对应&#xff1a; 注意安装对应版本&#xff0c;否则可能会出现一些未知的错误。 &#xff08;2&#xff09;拉取镜像 docker pull elasticsearch:7…

前后端请求响应

引入 在之前的例子中&#xff0c;我们编写了一个简单的web类&#xff0c;我们运行启动类&#xff0c;启动内嵌的tomcat后就可以在浏览器通过特定的路径访问tomcat中的应用程序。 但之前编写的程序仅仅是个简单的java类&#xff0c;其并未实现某个接口或继承某个类&…

VS2022编译32位OpenCV

使用环境 Visual Studio 2022 OpenCV: 4.7.0 cmake: 3.30.2一、使用CMake工具生成vs2022的openCV工程解决方案 打开cmake&#xff0c;选择opencv的源代码目录&#xff0c;创建一个文件夹&#xff0c;作为VS工程文件的生成目录 点击configure构建项目&#xff0c;弹出构建设置…

电子应用设计方案-12:智能窗帘系统方案设计

一、系统概述 本设计方案旨在打造便捷、高效的全自动智能窗帘系统。 二、硬件选择 1. 电机&#xff1a;选用低噪音、扭矩合适的智能电机&#xff0c;根据窗帘尺寸和重量确定电机功率&#xff0c;确保能平稳拉动窗帘。 2. 轨道&#xff1a;选择坚固、顺滑的铝合金轨道&…

MySQL系统优化

文章目录 MySQL系统优化第一章&#xff1a;引言第二章&#xff1a;MySQL服务架构优化1. 读写分离2. 水平分区与垂直分区3. 缓存策略 第三章&#xff1a;MySQL配置优化1. 内存分配优化Buffer Pool 的优化查询缓存与表缓存Key Buffer 2. 连接优化最大连接数会话超时连接池 3. 日志…

LLM - 计算 多模态大语言模型 的参数量(Qwen2-VL、Llama-3.1) 教程

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/143749468 免责声明&#xff1a;本文来源于个人知识与公开资料&#xff0c;仅用于学术交流&#xff0c;欢迎讨论&#xff0c;不支持转载。 影响 (…

光耦选型指南

一、指南说明 针对光偶选型和实际使用过程中出现因光偶特性变化引起的产品失效问题&#xff0c;提供指导。光耦属于易失效器件&#xff0c;选型和使用过程中要特别的小心。目前发现&#xff0c;因光偶的选型&#xff0c;光偶工作电流&#xff0c;CTR参数选型不合适&#xff0c…

git创建远程仓库,以gitee码云为例GitHub同理

git远程Remote服务端仓库构建的视频教程在这 Git建立服务端Remote远程仓库&#xff0c;gitee码云例&#xff0c;Github_哔哩哔哩_bilibili 1、登gitee码云/Github 登录 - Gitee.com https://github.com/ &#xff08;没账号的注册一下就行&#xff09; 点击如下图位置的创…

19.UE5道具掉落

2-21 道具掉落&#xff0c;回血、回蓝、升级提升伤害_哔哩哔哩_bilibili 目录 1.道具的创建&#xff0c;道具功能的实现 2.随机掉落 1.道具的创建&#xff0c;道具功能的实现 新建Actor蓝图&#xff0c;并命名为道具总类&#xff0c;添加一个Niagara粒子组件和一个碰撞箱bo…

排序算法(基础)大全

一、排序算法的作用&#xff1a; 排序算法的主要作用是将一组数据按照特定的顺序进行排列&#xff0c;使得数据更加有序和有组织。 1. 查找效率&#xff1a;通过将数据进行排序&#xff0c;可以提高查找算法的效率。在有序的数据中&#xff0c;可以使用更加高效的查找算法&…

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

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