[Linux]多线程详解

news2024/11/17 14:31:57

多线程

  • 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.coloradmin.cn/o/2242224.html

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

相关文章

替换OpenTSDB和HBase,宝武集团使用IoTDB助力钢铁设备智能运维

时序数据库 IoTDB 应用于宝武集团全基地钢铁时序数据管理&#xff0c;激活数据资产&#xff0c;赋能大型设备智能运维。 1. 背景概述 宝武装备智能科技有限公司&#xff08;以下简称&#xff1a;宝武智维&#xff09;是中国宝武设备智能运维专业化平台公司&#xff0c;30 余年始…

VSCode+ESP-IDF开发ESP32-S3-DevKitC-1(1)开发环境搭建

VSCodeESP-IDF开发ESP32-S3-DevKitC-1&#xff08;1&#xff09;开发环境搭建 1.开发环境搭建&#xff08;安装ESP-IDF&#xff09;2.开发环境搭建&#xff08;安装VS Code&#xff09;3.开发环境搭建&#xff08;VSCode中安装ESP-IDF插件及配置&#xff09; 1.开发环境搭建&am…

Ubuntu24 上安装搜狗输入法

link 首先在终端中依次输入以下代码 sudo apt update sudo apt install fcitx 找到语言支持 在终端中依次输入 sudo cp /usr/share/applications/fcitx.desktop /etc/xdg/autostart/ sudo apt purge ibus 进入网页 搜狗输入法linux-首页​ shurufa.sogou.com/linux 找到刚才下…

Qt文件目录操作

文件目录操作相关类 Qt 为文件和目录操作提供了一些类&#xff0c;利用这些类可以方便地实现一些操作。Qt 提供的与文件和目录操作相关的类包括以下几个&#xff1a; QCoreApplication&#xff1a;用于提取应用程序路径&#xff0c;程序名等文件信息&#xff1b;QFile&#x…

Session注入

Session注入 在进行Dll注入的时候&#xff0c;我们发现没法注入一些系统进程 提示我们缺少权限或者拒绝访问&#xff0c;甚至干脆就是什么反应都没有 这时候我们考虑往更加底层去跟函数&#xff0c;我们不能再使用在用户层所给我们的函数&#xff0c;我们自己去寻找内核层的…

深入List集合:ArrayList与LinkedList的底层逻辑与区别

目录 一、前言 二、基本概念 三、相同之处 四、不同之处 五、ArrayList 底层 六、LinkedList 底层 七、ArrayList 应用场景 八、LinkedList 应用场景 九、ArrayList和LinkedList高级话题 十、总结 一、前言 在Java集合的广阔舞台上&#xff0c;ArrayList与LinkedLis…

从建立TRUST到实现FAIR:可持续海洋经济的数据管理

1. 引言 随着我们对信息管理方式的信任&#xff0c;我们的社会对数字化数据的以来呈指数级增长。为了跟上大数据的需求&#xff0c;通过不断的努力和持续实践&#xff0c;对“good”数据管理方式的共识也在不断发展和演变。 加拿大正在建设国家基础设施和服务以及研究数据管理…

数据结构《栈和队列》

文章目录 一、什么是栈&#xff1f;1.1 栈的模拟实现1.2 关于栈的例题 二、什么是队列&#xff1f;2.2 队列的模拟实现2.2 关于队列的例题 总结 提示&#xff1a;关于栈和队列的实现其实很简单&#xff0c;基本上是对之前的顺序表和链表的一种应用&#xff0c;代码部分也不难。…

一.Spring cloud--Consul服务注册与发现(2)

安装并运行Consul (1)官网下载 (2)下载完成后只有一个consul.exe文件,对应全路径下查看版本号信息 (3)使用开发模式启动 consul agent -dev 通过以下地址可以访问Consul的首页: http://localhost:8500 结果页面

【搜索结构】AVL树的学习与实现

目录 什么是AVL树 AVL树的定义 插入函数的实现 左单旋和右单旋 左右双旋与右左双旋 什么是AVL树 AVL树实际上就是二叉搜索树的一种变体&#xff0c;我们都知道二i叉搜索树可以将查找的时间复杂度提升到O(logn)&#xff0c;极大提升搜索效率。但是在极端情况下&#xff0c;当…

IPTV智慧云桌面,后台服务器搭建笔记

环境CentOs7.9 &#xff0c;安装宝塔yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh 访问宝塔&#xff0c;修改服务器端口安全组端口 26029 注意&#xff01;&#xff01;&#xff01;&#xff01…

IDEA leetcode插件代码模板配置,登录闪退解决

前言 最近换电脑&#xff0c;配置idea时和原来的模板格式不一样有点难受&#xff0c;记录一下自己用的模板&#xff0c;后期换电脑使用&#xff0c;大家也可以使用&#xff0c;有更好的地方可以分享给我~ IDEA leetcode插件代码模板配置,登录闪退解决 前言1 下载IDEA leetcode…

Django基础用法+Demo演示

Django快速上手 参考: Django快速上手 再写几个页面 编辑demo1/urls.py, 添加URL和视图函数映射 urlpatterns [path(index/, views.index),path(user/list/, views.user_list),path(user/add/, views.user_add), ]编辑app01/views.py&#xff0c;添加几个函数 from djang…

蓝桥杯-洛谷刷题-day3(C++)

目录 1.忽略回车的字符串输入 i.getline() ii.逐个字符的识别再输入 2.获取绝对值abs() 3.做题时的误区 4.多个变量的某一个到达判断条件 i.max() 5.[NOIP2016 提高组] 玩具谜题 i.代码 6.逻辑上的圆圈 i.有限个数n的数组 7.数组的定义 i.动态数组 1.忽略回车的字符串输…

Redis在高性能缓存中的应用

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 Redis在高性能缓存中的应用 Redis在高性能缓存中的应用 Redis在高性能缓存中的应用 引言 Redis 概述 定义与原理 发展历程 Redi…

AOP实现上下游泳道隔离RPC调用

在平时代码项目代码测试的过程中&#xff0c;“隔离”思想就经常被用上&#xff0c;比方说多个并行开发的需求都需要用到服务 A 的能力&#xff0c;但是又需要同时部署 A 不同的代码分支&#xff0c;这个时候“泳道隔离”机制就显得尤为重要了。“泳道隔离”即将相同代码仓库的…

TCP/IP--Socket套接字--JAVA

一、概念 Socket套接字&#xff0c;是由系统提供⽤于⽹络通信的技术&#xff0c;是基于TCP/IP协议的⽹络通信的基本操作单元。 基于Socket套接字的⽹络程序开发就是⽹络编程。 二、分类 1.流套接字 使用传输层TCP协议。TCP协议特点&#xff1a;有链接、可靠传输、面向字节流…

号卡分销系统,号卡系统,物联网卡系统源码安装教程

号卡分销系统&#xff0c;号卡系统&#xff0c;物联网卡系统&#xff0c;&#xff0c;实现的高性能(PHP协程、PHP微服务)、高灵活性、前后端分离(后台)&#xff0c;PHP 持久化框架&#xff0c;助力管理系统敏捷开发&#xff0c;长期持续更新中。 主要特性 基于Auth验证的权限…

平衡二叉搜索树之 红黑 树的模拟实现【C++】

文章目录 红黑树的简单介绍定义红黑树的特性红黑树的应用 全部的实现代码放在了文章末尾准备工作包含头文件类的成员变量和红黑树节点的定义 构造函数和拷贝构造swap和赋值运算符重载析构函数findinsert【重要】第一步&#xff1a;按照二叉搜索树的方式插入新节点第二步&#x…

线性数据结构

数组 数组&#xff08;Array&#xff09; 是一种很常见的数据结构。它由相同类型的元素&#xff08;element&#xff09;组成&#xff0c;并且是使用一块连续的内存来存储。 我们直接可以利用元素的索引&#xff08;index&#xff09;可以计算出该元素对应的存储地址。 数组…