【Linux】线程id与互斥(线程三)

上一期我们进行了线程控制的了解与相关操作,但是扔就有一些问题没有解决在这里插入图片描述
本章第一阶段就是解决tid的问题,第二阶段是进行模拟一个简易线程库(为了加深对于C++库封装linux原生线程的理解),第三阶段就是互斥。

目录

  • 线程id:
    • LWP与tid:
    • 动态库的加载:
    • 线程id:
    • 如何理解维护在库中:
    • 再次感受一下pthread_join():
    • 线程局部存储:
  • 封装线程库:
    • 封装:
  • 互斥:

线程id:

LWP与tid:

我们还是先来写一段简单的代码进行验证一下LWP与线程id的关系。

代码:
在这里插入图片描述
验证结果:在这里插入图片描述

在这里插入图片描述
足以观察到LWP与tid的差距是非常大的。

这说明给用户提供的线程id并不是内核中的LWP,而是自己维护的一个唯一值。
自己就是pthread库。

虽然刚开始觉得不符合常理,但仔细想一想而本该如此:
因为linux并没有线程,但是我们用户需要线程的概念,所以pthread库充当了一个中间角色,封装linux中的轻量级进程,因此,并不需要呈现给用户LWP的值,给用户呈现自己封装的线程id即可。就像C语言中的FILE,我们直接用库封装好的,并不需要在使用文件描述符fd了,也不需要展现给用户。

因为库提供了线程id,所以库也要对pthread进行管理,怎么理解呢?
可以理解为学校给你提供了学号,所以学校要对你进行管理。

我们的linux肯定提供了轻量级进程的调度系统调用,但是一个线程不仅仅需要被调度,也需要一个id,栈大小,被谁启动…这些属性也是由库做管理的!

针对管理我们要展开一下。

动态库的加载:

那就要先看一下线程库的加载,首先动态库和我们的程序肯定都是在磁盘上的文件。
在这里插入图片描述

当我们./运行时,会建立内核数据结构 + 加载数据与代码。

在这里插入图片描述
当我们执行到pthread_create时,因为我们还未加载动态库,会触发缺页中断,去加载动态库,再将动态库映射到共享区。
在这里插入图片描述
此时我们就可以正常去执行我们的pthread_create去创建线程了。

而我们也说过库需要对我们的线程id,栈的大小…进行维护,也就是进行管理

而管理就需要对该对象进行描述再进行组织,下图就是描述他的结构体pthread_t。在这里插入图片描述
其中的struct pthread是用户最基本的线程属性,线程局部存储我们稍后再来进行讲解。而编程栈就是我们常说的每个线程都有一个独立的线程栈!

组织我们可以看成是使用一个数组进行组织起来的。

线程id:

所以以后想找线程属性,拥有地址即可进行管理,而我们的tid就是相应的pthread_t的地址。

如何理解维护在库中:

我们还是以FILE进行举例。
我们的FILE是一个结构体:

struct FILE
{int fd;char buff[N];...
}

我们打开一个文件会得到一个FILE的指针。

而这个FILE结构体指针就维护在标准库中,进入这个函数时,会执行malloc(sizeof(struct FILE))类似的代码在堆上申请空间,等执行完之后返回给用户FILE*,让用户进行操控。所以我们也就可以理解维护在库中了。

就像我们使用STL中的各种容器,不需要管底层是如何扩容的。

再次感受一下pthread_join():

在这里插入图片描述
所以我们也就理解了pthread_create时的attr在这里插入图片描述
这就是用来控制pthread_t的属性,比如控制栈的大小…

总结:linux线程 = pthread库 + LWP,其中内核维护的LWP与动态库中维护的线程是1:1的。

但是同学们,我们该如何保障新线程轻量级进程会使用你指定的栈?
因为我们的轻量级进程中有一个系统调用:clone。
在这里插入图片描述
第一个是回调函数,第二个就是指定的栈,第三个是参数,所以pthread库本质就是对这样的一堆系统调用进行封装。

线程局部存储:

现在还剩最后一个问题,线程局部存储是啥?在这里插入图片描述
我们先来看这样一段代码:
搞一个全局变量,新线程改,主线程读取。
在这里插入图片描述

现象: 一改具改,符合预期。

但是如果我们想要互相不影响,也就是新主线程虽然用同一个全局变量名字,但是实际却是两个地址。
我们可以加入编译选项__thread
注意:这个只可以修饰全局的内置类型。

在这里插入图片描述

现象:可以看到虚拟地址也不相同。
在这里插入图片描述
结论:虽然看起来还是用一个,但实际上各自私有一份

封装线程库:

本质是为了更好的理解C++11是如何进行封装的。

我们的目标是实现如下几个接口:
在这里插入图片描述
也可以在来一个GetStatus,调用可以观察到是否正在运行。

封装:

在这里插入图片描述
先来解释一下成员变量,_name就是线程名字,_tid是线程id,_func是用户传递来的要执行的函数,_isRunning是代表当前程序是否在执行。


在实现时有两个的坑点。
其一:因为我们是进行封装,所以是在类中实现。
但是我们将routine写出了之后却找不到对应routine,这是因为类中的成员默认有隐含的this指针,所以参数的个数就不匹配了。
在这里插入图片描述
解决这种问题的办法很多,但我们最喜欢用static进行修饰,这样就不会有this指针了,这个函数属于整个类。
在这里插入图片描述
可是这样我们就无法访问类中的成员变量了,因为没有this指针~

那怎么办?
把this指针当做参数传给routine!

在这里插入图片描述
这样就可以调用外部给我们传的指定函数了。
可是这样调用未免有些丑陋。
在这里插入图片描述
在将stop,join进行填补即可,注意,我们的构造函数需要一个你指定的名字和待执行函数。

主函数代码:
在这里插入图片描述
现象:

在这里插入图片描述
也是完成了我们预期的工作。

源代码:

#include <iostream>
#include <string>
#include <unistd.h>
#include <cstdio>namespace cyc
{class mythread{public:typedef void (*func_t)(std::string);mythread(const std::string &name, func_t func) : _name(name), _func(func), _isRunning(false){}~mythread(){}void Excute(){_isRunning = true;_func(_name);_isRunning = false;}static void *routine(void *arg){mythread *self = static_cast<mythread *>(arg);self->Excute();return nullptr;}void Start(){int n = ::pthread_create(&_tid, nullptr, routine, (void *)this);if (n != 0){perror("pthread_create fail");exit(1);}}void Stop(){if (_isRunning){pthread_cancel(_tid);_isRunning = false;}}void Join(){int n = pthread_join(_tid, nullptr);if (n != 0){perror("pthread_join fail");exit(1);}}std::string GetStatus(){if(_isRunning) return "Running";else return "sleeping";}private:std::string _name;pthread_t _tid;func_t _func;bool _isRunning;};
}

于是我们就完成了一个很简易的封装~

互斥:

多个线程能够看到的资源叫做共享资源。
但是也会有一些问题,比如我们线程通信,一个线程想写hello world,但是刚写了hello就被另一个进程独走了,叫做读写不一致,
所以我们需要对共享资源做保护。

其中最简单的方法是互斥。

但是我们总要先见一见吧。
我们模拟一个抢票的代码,假设一共有1w张票,创建4哥线程同时去抢,每抢一次记录一下抢之前的票数,当票数<=0就是出现了问题。

我们就是用刚刚模拟实现的线程进行操作。
代码:
在这里插入图片描述
现象:
在这里插入图片描述
果然出现了0甚至负数,这就证明我们的抢票提供非常的失败~

可是原理是什么呢?

首先我们要有两个储备知识。
其一是判断也是一种运算,为逻辑运算。
一共有两种运算,分别为算术运算与逻辑运算,简称算罗运算。

其二是线程的切换,CPU内寄存器只有一套,但是拥有的数据有多套。切换时带走自己的数据,回来时会回复!

对于1来说,逻辑判断至少分为3步,虽然语法上表现为3步,但是实际转换到汇编有2-3步。在这里插入图片描述
我们假设线程1在还有最后一张票时进入,已经判断完毕了,但是此时tickets还没进行--,这时时间片到了,线程1被切换,带走了当前寄存器的值与记录执行到的语句。同理2,3,4也都分别执行完判断语句就被切换这就有很大的问题了。

因为只有一张票却有4个线程进入了,等线程a,b,c,d分别恢复时将数据又放回到寄存器中。
注意:进行--时需要将数据重读,修改,在放回内存中这三步

所以票数就变为0,-1,-2…

下章继续~

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

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

相关文章

链在一起怎么联机 链在一起远程同玩联机教程

steam中最近特别热门的多人跑酷冒险的游戏&#xff1a;《链在一起》&#xff0c;英文名称叫做Chained Together&#xff0c;在游戏中我们需要开始自己的旅程&#xff0c;在地狱的深处&#xff0c;与我们的同伴被链在一起。我们的任务是通过尽可能高的攀登逃离地狱。每一次跳跃都…

Python第三方库GDAL 安装

安装GDAL的方式多种&#xff0c;包括pip、Anaconda、OSGeo4W等。笔者在安装过程中&#xff0c;唯独使用pip安装遇到问题。最终通过轮子文件&#xff08;.whl&#xff09;成功安装。 本文主要介绍如何下载和安装较新版本的GDAL轮子文件。 一、GDAL轮子文件下载 打开Github网站…

Python学习打卡:day16

day16 笔记来源于&#xff1a;黑马程序员python教程&#xff0c;8天python从入门到精通&#xff0c;学python看这套就够了 目录 day16116、SQL 基础和 DDLSQL的概述SQL语言的分类SQL的语法特征DDL — 库管理DDL — 表管理 117、SQL — DMLDML概述数据插入 INSERT数据删除 DEL…

深入理解 Dubbo:分布式服务框架的核心原理与实践

目录 Dubbo 概述Dubbo 的架构Dubbo 的关键组件 服务提供者&#xff08;Provider&#xff09;服务消费者&#xff08;Consumer&#xff09;注册中心&#xff08;Registry&#xff09;监控中心&#xff08;Monitor&#xff09;调用链追踪&#xff08;Trace&#xff09; Dubbo 的…

专题页面设计指南:从构思到实现

如何设计专题页&#xff1f;你有什么想法&#xff1f;专题页的设计主要以发扬产品优势为核心。一个好的专题页可以从不同的角度向用户介绍产品&#xff0c;扩大产品的相关优势&#xff0c;表达产品的优势&#xff0c;让用户在短时间内了解产品。因此&#xff0c;在设计详细信息…

纯血鸿蒙Beta版本发布,中国华为,站起来了!

2024年6月21日至23日&#xff0c;华为开发者大会2024&#xff08;HDC 2024&#xff09;于东莞盛大举行。 此次大会不仅在会场设置了包括鸿蒙原生应用、统一生态统一互联等在内的11个展区&#xff0c;以供展示HarmonyOS NEXT的强大实力&#xff0c;还对外宣布了HarmonyOS的最新进…

240627_关于CNN中图像维度变化问题

240627_关于CNN中图像维度变化问题 在学习一些经典模型时&#xff0c;其中得维度变化关系总搞不太明白&#xff0c;集中学习了以下&#xff0c;在此作以梳理总结&#xff1a; 一般来说涉及到的维度变换都是四个维度&#xff0c;当batch size4&#xff0c;图像尺寸为640*640&a…

kylin v10 离线安装chrome centos离线安装chrome linux离线安装谷歌浏览器

1. 先用自己联网的计算机&#xff0c;下载离线安装包&#xff0c;浏览器输入链接下载安装包&#xff1a; https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm 1.2. 信创环境不用执行下面&#xff0c;因为没网 1.3. 若为阿里云服务器&#xff0c;或服…

AR导航技术加持,图书馆阅读体验智慧升级

在信息爆炸的今天&#xff0c;图书馆作为知识的宝库&#xff0c;其藏书量和种类日益增多。然而&#xff0c;传统的图书馆导航方式已逐渐无法满足用户对快速、准确定位图书的需求。本文将探讨图书馆AR地图导航的实现原理、技术优势、功能特点以及市场前景&#xff0c;揭示为何AR…

VS studio2019配置远程连接Ubuntu

VS studio2019配置远程连接Ubuntu 1、网络配置 &#xff08;1&#xff09;获取主机IP &#xff08;2&#xff09;获取Ubuntu的IP &#xff08;3&#xff09;在 windows 的控制台中 ping 虚拟机的 ipv4 地址&#xff0c;在 Ubuntu 中 ping 主机的 ipv4 地址。 ubuntu: ping…

【Linux】对共享库加载问题的深入理解——基本原理概述

原理概述 【linux】详解——库-CSDN博客 共享库被加载后&#xff0c;系统会为该共享库创建一个结构&#xff0c;这个结构体中的字段描述了库的各种属性。在内存中可能会加载很多库&#xff0c;每一个库都用一个结构体描述。把这些结构体用一些数据结构管理起来&#xff0c;系…

WordPress Dokan Pro插件 SQL注入漏洞复现(CVE-2024-3922)

0x01 产品简介 WordPress Dokan Pro插件是一款功能强大的多供应商电子商务市场解决方案,功能全面、易于使用的多供应商电子商务平台解决方案,适合各种规模的电商项目。允许管理员创建一个多卖家平台,卖家可以注册账户并在平台上创建自己的店铺,展示和销售自己的产品。提供…

kali下安装使用蚁剑(AntSword)

目录 0x00 介绍0x01 安装0x02 使用1. 设置代理2. 请求头配置3. 编码器 0x00 介绍 蚁剑&#xff08;AntSword&#xff09;是一个webshell管理工具。 官方文档&#xff1a;https://www.yuque.com/antswordproject/antsword 0x01 安装 在kali中安装蚁剑&#xff0c;分为两部分&am…

Zabbix 监控系统部署

Zabbix 监控系统部署 Zabbix是一个企业级开源分布式监控解决方案&#xff0c;可监控网络的众多参数以及服务器、虚拟机、应用程序、服务、数据库、网站、云等的运行状况和完整性。 Zabbix 使用灵活的通知机制&#xff0c;允许用户为几乎任何事件配置基于电子邮件的警报。这允许…

java发送图文到公众号

这两天接到了一个新任务&#xff0c;通过后台管理编写文章&#xff0c;发送到官网的同时&#xff0c;推送一份到公众号&#xff0c;研究了一下微信的文档&#xff0c;发现不难&#xff0c;只需要有几个注意点就可以了。 注意&#xff1a; 微信公众号只能访问微信自己上传的图片…

STM32单片机实现串口IAP升级

一.概述 1.要实现串口IAP升级&#xff0c;首先要编写一个bootloader程序&#xff0c;然后再写支持IAP的app程序&#xff1b; 2.keil下bootloader的程序rom和ram设置 3.app程序要用bin文件 注&#xff1a;本文以STM32H743举例&#xff0c;其他stm32单片机IAP升级原理类似。 …

达梦数据库的系统视图v$database

达梦数据库的系统视图v$database 基础信息 OS版本&#xff1a; Red Hat Enterprise Linux Server release 7.9 (Maipo) DB版本&#xff1a; DM Database Server 64 V8 DB Version: 0x7000c 03134284132-20240115-215128-20081在达梦数据库&#xff08;Dameng Database&#xf…

Java——Lambda表达式

1. 背景 Lambda表达式是JavaSE 8中一个重要的新特性。Lambda表达式允许你通过表达式来代替功能接口。 Lambda表达式就和方法一样&#xff0c;它提供了一个正常的参数列表和一个使用这些参数的主体(body&#xff0c;可以是一个表达式或一个代码块)。 Lambda 表达式&#xff08;…

C# YoloV8 模型效果验证工具(OnnxRuntime+ByteTrack推理)

C# YoloV8 模型效果验证工具(OnnxRuntimeByteTrack推理) 目录 效果 项目 代码 下载 效果 模型效果验证工具 项目 代码 using ByteTrack; using OpenCvSharp; using System; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using Sys…

【win11】Mouse without Borders安装问题以管理员权限安装msi文件

【win11】Mouse without Borders安装问题&以管理员权限安装msi文件 Mouse without Borders安装问题解决&以管理员权限安装msi文件启动Windows Installer服务以管理员权限安装msi文件 参考文献 Mouse without Borders安装问题 在win11下我双击MouseWithoutBorders2.2.1…