linux的线程概念

目录

1.原理

2.线程的周边概念

3.创建线程的接口

1.pthread_create

2.pthread_join

3.pthread_detach

4.终止线程

5.C++11封装的多线程库

4.线程库的大概结构

5.__thread(只能修饰内置类型)

6.线程的互斥

1.了解原理

2.加锁

1.接口

2.代码示范

3.相关问题

2.锁的原理

3.封装锁


1.原理

这理解线程,一定要理解进程的原理。我们先来简单看一下进程的原理图:

地址空间是进程的资源窗口,那如何理解线程呢?线程:是进程内的一个个的执行分支。线程的执行粒度要比进程更细!

而这些线程都是执行流,因为cpu只有调度执行流的概念。所以在linux中的执行流可以说是轻量级的进程:线程<=执行流<=进程(如果该进程只有一个线程,则线程就是进程就是执行流,但是该进程有多个线程,则线程就是执行流)。但是注意在其他环境下(比如windows)就不是这样管理线程的,而是:

这样就其他的增大了管理线程的代价,而linux就发现线程和进程的pcb差不多,所以就一同规定了!

linux的实现方案:
1.在linux中,线程在进程“内部”执行,线程在进程的地址空间内运行----任何执行流要执行都要资源!地址空间是进程的资源窗口,就当做共享的了!

2.在linux中,线程的执行粒度要比进程要更细-----线程执行进程代码的一部分。

2.线程的周边概念

其实共享的还有:栈,寄存器,线程id,一组寄存器,errno,信号屏蔽字,调度优先级。

3.创建线程的接口

由于linux没有很明确的线程的概念,只有轻量级进程(线程)的概念。所以不会直接提供给我们线程的系统调用,只有轻量级进程的接口,我们需要的是线程的-------因此pthread线程库,在应用层给我们封装了线程的库。(几乎所有的linux平台,都是默认自带这个库的)

1.pthread_create

第一个参数--输出型参数thread id(告诉主线程开辟的线程id),第二个---是开辟新线程的属性,一般是设为nullptr,用默认的属性就好,第三个参数就是要新线程执行的任务函数,第四个就是要传入这个函数的形参。

注意左边的id是用户级的线程id,而右边的LWP是内核级的线程id

2.pthread_join

和子进程一样,线程结束不回收的话,可能会导致内存泄露。

第二个参数是知道线程执行函数的返回值的。返回的是void*,那么要在pthread_join的retval的输出型参数获得的话,就要是void**。

但是我们发现,我们之前了解过进程有三种结束状态,1.代码没跑完,2.代码跑完,输出码异常3.代码跑完,输出码正常。那如果线程中途出异常了怎么办?

次线程出异常,整个进程将全部结束!

3.pthread_detach

这是让主线程不需要等待其他线程的函数:

4.终止线程

5.C++11封装的多线程库

如果你的代码需要在多个平台下运行的话,就使用C++封装的库,每当使用这些库时,里面都是加载相对应打开该环境下线程的库,所以才说C++是支持跨平台的,如果你使用上面的函数在vs编译器(window环境)是绝对不可能运行的起来的!

4.线程库的大概结构

其实这个函数才是最底层的函数,fn就是thread_create的第三个参数,child_stack就是内部自定义一个栈。flags其实是问你要不要和地址空间实现共享,我们默认都是要的!

那么如何先描述再组织的呢?

5.__thread(只能修饰内置类型)

上面代码的g_val全局变量肯定是被共享的,但是__thread修饰过之后,就可以变成全局变量,但是被每个线程独有的:

那有什么用呢?我们线程里面函数定义变量也可以啊,况且还不能修饰自定义类型。但是如果在线程执行的函数里面,还包含函数,并且需要用到这个变量,那是不是就只能通过传参的方式来使用,但是这个就可以少传点参数了!

6.线程的互斥

先看一下接下来的代码:

我们已经判断ticket>0了,为什么还会出现这个情况?

1.了解原理

但是由于上面这种情况发生的概率很小,所有就用了上面的代码来解释:

线程1判断ticket>0刚好时间片结束,然后给线程2,此时还没有进行ticket--操作,依旧可以进入if语句,所以才导致了这个现象!

2.加锁

1.接口

pthread_mutex_t就是结构体,init和destroy就是初始化和删除,但是如果把该结构体=PTHREAD_MUTEX_INITIALIZER就不需要初始化和删除了。

pthread_mutex_lock 和unlock两个函数中间就是加锁的区间。

2.代码示范

但是看结果发现:抢票的都是2号线程,原因是2号线程抢到锁之后,在释放锁的同时又申请锁了。所以我们需要改进一下:

3.相关问题

1.申请锁成功,才能往后执行,不成功,阻塞等待。但是在临界区中,线程可以被切换吗?答案是肯定的,如果你临界区代码多,cpu也不可能只给你运行一个。当然切换的肯定是其他的线程,那些没有锁的线程肯定还在堵塞当中。所以当前线程访问临界区的过程,对于其他线程是原子的。

2.但是锁本身就是共享资源,所以申请锁和释放锁本身就是被设计成为了原子性操作,那是如何做到的呢?

2.锁的原理

movb就是将当前线程的al寄存器中的值制0,然后将mutex内存中的值做交换---exchgb。这条指令才是最重要的,本质就是把数据交换到线程的硬件上下文。所有寄存器每个cpu中只有一份但是内容是更着线程走的!所以一旦交换后,不管你线程怎么切换,其他线程拿到手的mutex都是0,只有那一个线程中的al寄存器中的值是1.---把一把共享锁,让一个线程以一条汇编的方式,交换到知己的上下文当中。

看到解锁是movb而不是xchgb,所以可以看的出来,不一定要同一个线程来解锁,这样可以避免拿到锁的线程万一直接bebug,还把锁拿走了,所以我们可以通过别的锁来解。

3.封装锁

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

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

相关文章

机器学习深度学习中的上采样技术

上采样技术&#xff0c;也称为增取样或内插&#xff0c;是信号处理和图像处理中常用的技术&#xff0c;用于增加信号或图像的采样率或分辨率&#xff0c;从而使其变得更大。 在图像处理中&#xff0c;上采样主要用于放大图像&#xff0c;增加图像的尺寸或分辨率。 上采样的实…

【网络编程】Linux网络内核结构以及分布剖析

hello &#xff01;大家好呀&#xff01; 欢迎大家来到我的网络编程系列之Linux网络内核结构以及分布剖析&#xff0c;在这篇文章中&#xff0c;你将会学习到在Linux内核中如何实现网络数据的输入和输出的&#xff0c;并且我会给出源码进行剖析&#xff0c;以及手绘UML图来帮助…

如何应对Android面试官 -> ActivityManagerService 是怎么启动的?

前言 本章主要讲解下 什么是 AMS&#xff0c;以及它是如何启动的&#xff1b; SystemServer SystemServer 通过按下电源键接通电源之后就会启动 BootRoom&#xff0c;BootRoom 就会拉起一个 BootLoader 程序&#xff0c;此程序会拉起 Linux Kernel「系统内核」&#xff0c;我们…

树 和 二叉树

目录 一、树 1、初识树 2、树的一些概念 3、树的表示形式 二、二叉树 1、初识二叉树 2、两种特殊的二叉树 3、二叉树的性质 4、二叉树的遍历 5、实现一棵二叉树 6、二叉树题目&#xff08;没代码的后面会给补上&#xff09; 一、树 1、初识树 &#xff08;1&…

【Java】图片处理工具ImageMagick简介及其在Java中的应用

ImageMagick是一款强大的图像处理软件&#xff0c;它可以用于创建、编辑、合并和转换图像。它支持超过200种图像格式&#xff0c;并且提供了丰富的功能&#xff0c;包括图像缩放、旋转、裁剪、加水印、添加特效等。ImageMagick还支持批量处理图像&#xff0c;可以通过命令行或者…

浅谈网络代理 proxy

总会有各种各样需要用到代理的场景 比如批量提交漏洞、批量注册、批量扫描.... 简单总结一下 代理简介 IP 代理是一种网络技术&#xff0c;通过这种技术&#xff0c;用户可以隐藏其真实的 IP 地址&#xff0c;并使用另一个 IP 地址来代表自己进行互联网上的活动。IP 代理通常由…

xhci 数据结构

xhci 数据结构 xhci 数据结构主要在手册上有详细的定义&#xff0c;本文根据手册进行归纳总结&#xff1a; 重点关注的包括&#xff1a; device contexttrb ringtrb device context设备上下文 设备上下文数据结构由xHC管理&#xff0c;用于向系统软件报告设备配置和状态信息。…

《CSS 知识点》仅在文本有省略号时添加 tip 信息

html <div ref"btns" class"btns"><div class"btn" >这是一段很短的文本.</div><div class"btn" >这是一段很短的文本.</div><div class"btn" >这是一段很长的文本.有省略号和tip.<…

MongoDB副本集部署(windows)

环境准备 本教程演示mongodb4.4 副本集部署&#xff08;一主两从&#xff0c;伪分布式&#xff09; 节点配置主节点localhost:27017从节点1localhost:27018从节点2localhost:27019 每一个节点&#xff08;实例&#xff09;都创建对应的数据文件&#xff08;data&#xff09;…

MySQL中的存储过程详解(上篇)

使用语言 MySQL 使用工具 Navicat Premium 16 代码能力快速提升小方法&#xff0c;看完代码自己敲一遍&#xff0c;十分有用 拖动表名到查询文件中就可以直接把名字拉进来中括号&#xff0c;就代表可写可不写 目录 1.认识存储过程 1.1 存储过程的作用 1.2 存储过程简介…

OpenHarmony轻量系统开发【13】鸿蒙小车开发

13.1 小车介绍 基于鸿蒙系统 Hi3861 的WiFi小车 首先&#xff0c;我们得有一套WiFi小车套件&#xff0c;其实也是Hi3861 加上电机、循迹模块、超声波等模块。 小车安装完大概是这样&#xff1a; 13.2 电机驱动 我们这里先只做最简单的&#xff0c;驱动小车的电机&#xff…

ModuleNotFoundError: No module named ‘llama_index.readers“解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

Centos7,部署etcd集群,基于二进制包,https安全通讯

由于etcd集群https通讯&#xff0c;所以需要自建CA数字证书&#xff0c;学习使用https部署etcd集群前&#xff0c;可以先完成一下&#xff0c;基于http通信的etcd集群&#xff1a; 关于CA原理以及工作可以阅读&#xff0c;以下两篇文章&#xff1a; CA工作原理 对称加密与非对…

【洛谷题解】 CF1468E Four Segments

分析 我们可以知道&#xff0c;如果两个相对的边所在的棍子的长度分别为 a a a 和 b b b&#xff0c;那么这两条边最大只能就为 min ⁡ ( a , b ) \min(a,b) min(a,b)。所以如果让最长的棍子&#xff08;设其长度为 a a a&#xff09;与最短的棍子&#xff08;设其长度为 …

怎样将PDF转成PPT,有免费的工具吗?

PDF转换为PPT的需求在现代办公和学习中越来越常见。很多人可能遇到过需要将PDF文件中的内容转移到PPT中以方便编辑和展示的情况。幸运的是&#xff0c;现在市面上有许多工具可以帮助我们实现这一目标&#xff0c;而且其中不乏一些免费的选项。本文将详细介绍如何使用这些免费工…

自然语言处理、大语言模型相关名词整理

自然语言处理相关名词整理 零样本学习&#xff08;zero-shot learning&#xff09;词嵌入&#xff08;Embedding&#xff09;为什么 Embedding 搜索比基于词频搜索效果好&#xff1f; Word2VecTransformer检索增强生成&#xff08;RAG&#xff09;幻觉采样温度Top-kTop-p奖励模…

全网最完整的软件测试面试八股文

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 关注公众号&#xff1a;互联网杂货铺&#xff0c;回复1 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 Part1 1、你的测试职业发展是什么&#xff1f; 测试经…

指定不同版本的jdk运行maven

背景 最近遇到一个业务上问题&#xff0c;使用maven执行线上打包的一个操作&#xff0c;但是java项目有jdk8&#xff0c;有的是jdk11还有的是jdk17的&#xff0c;如何根据不同的项目jdk版本来执行maven呢&#xff1f; 解决方案 这里是临时多版本动态打包&#xff0c;所以不能…

Python | Leetcode Python题解之第24题两两交换链表中的节点

题目&#xff1a; 题解&#xff1a; class Solution:def swapPairs(self, head: ListNode) -> ListNode:dummyHead ListNode(0)dummyHead.next headtemp dummyHeadwhile temp.next and temp.next.next:node1 temp.nextnode2 temp.next.nexttemp.next node2node1.next…