【linux】线程(二)

10. pthread_t 类型

注意:

  1. 每一个线程的库级别的tcb的起始地址,就是线程的 tid
  2. 每一个线程都有自己独立的栈结构
  3. 线程和线程之间,也是可以被其他线程看到并访问的(比如全局函数)

代码

如果想要进程拥有私人的全局变量(即线程库里面的线程局部存储):

__stread 修饰 变量(只能是内置类型的,不能是自定义类型的) ,如:

__stread int val

注意:

__stread 是编译选项

代码

11. linux线程互斥

(一)进程线程间的互斥相关背景概念

  1. 临界资源:多线程执行流共享的资源就叫做临界资源
  2. 临界区:每个线程内部,访问临界资源的代码,就叫做临界区
  3. 互斥:任何时刻,互斥保证有且只有一个执行流进入临界区,访问临界资源,通常对临界资源起保护作用
  4. 原子性(后面讨论如何实现):不会被任何调度机制打断的操作,该操作只有两态,要么完成,要么未完成
  5. 多线程并发访问共享资源的时候,容易发生数据不一致问题

抢票举例

if ( tickets > 0) // 判断

{

tickets--; //抢到票了

}

注意:

由于是 tickets-- 这一步是三条汇编指令去执行

  1. 把 tickets 拷贝到CPU寄存器中
  2. CPU寄存器的值--
  3. CPU寄存器的值拷贝到内存

发生错误可能原因:

  1. if 语句判断条件为真以后,代码可以并发的切换到其他线程
  2. tickets-- 操作本身就不是一个原子操作

注意:

要解决数据不一致问题,需要做到三点:

  1. 代码必须要有互斥行为:当代码进入临界区执行时,不允许其他线程进入该临界区。
  2. 如果多个线程同时要求执行临界区的代码,并且临界区没有线程在执行,那么只能允许一个线程进入该临界区
  3. 如果线程不在临界区中执行,那么该线程不能阻止其他线程进入临界区

要做到这三点,本质上就是需要一把锁。Linux上提供的这把锁叫互斥量

(二)互斥量

互斥量相关函数

初始化互斥量

初始化互斥量有两种方法:

1. 静态分配:

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER

注意:

此时不需要对 pthread_mutex_t 类型变量做初始化和销毁处理(即不需要调用 pthread_mutex_init 和 pthread_mutex_destroy 函数)

2. 动态分配:

int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict

attr);

参数:

mutex:要初始化的互斥量

attr:互斥量的属性,一般设置成NULL

注意:

这个函数一定要搭配 pthread_mutex_destroy一起使用

销毁互斥量

int pthread_mutex_destroy(pthread_mutex_t *mutex);

注意:

  1. 不要销毁一个已经加锁的互斥量
  2. 已经销毁的互斥量,要确保后面不会有线程再尝试加锁

互斥量加锁和解锁

加锁 :int pthread_mutex_lock(pthread_mutex_t *mutex);

解锁 :int pthread_mutex_unlock(pthread_mutex_t *mutex);

返回值:成功返回0,失败返回错误号

注意:

1.  调用 pthread_ lock 时,可能会遇到以下情况:

互斥量处于未锁状态,该函数会将互斥量锁定,同时返回成功

互斥量处于加锁状态,该线程会被阻塞,执行流处于被挂起,等待操作系统唤醒(即互斥量解锁了)

2.  哪个线程都可以对互斥量解锁,和加锁的线程是哪个无关

3.  即使只有一个线程,也可能由于操作不当,被阻塞挂起(比如:调用了两次加锁)

4.  如果申请了锁的资源,一定要把它释放掉

5.  加了锁的临界区的代码发生线程切换,也不会影响结果的正确

(三)加锁

  1. 加锁的本质:用时间来换安全
  2. 加锁的表现:线程对于临界区代码串行执行
  3. 加锁的原则:尽量要保证临界区的代码少

注意:

  1. 纯互斥环境下,如果锁分配的不合理,容易导致其他线程的饥饿问题(线程对锁的竞争能力可能不同,比如一个线程释放了锁,又能立刻拿到锁资源,导致其他线程一直阻塞)
  2. 不一定是有互斥,必有饥饿,纯互 m斥的场景,就用互斥
  3. 解决饥饿:让所有的线程获取锁资源,是按一定的顺序获取 --------- 叫同步

(三)互斥性原理

锁也是共享资源,为了维护其他临界资源,应该先保护自己的资源

锁的实现原理:

为了实现互斥锁操作,大多数体系结构都提供了swap或exchange指令(在硬件芯片上都有对应的指令集),该指令的作用是把寄存器和内存单元的数据相交换,由于只有一条指令,保证了原子性,即使是多处理器平台,访问内存的 总线周期也有先后,一个处理器上的交换指令执行时另一个处理器的交换指令只能等待总线周期

把lock和unlock的伪代码改一下:

 注意:

  1. 寄存器不等于寄存器的内容(寄存器实际上很多时候,得到的数据是上下文数据)
  2. 线程在执行的时候,将共享资源,加载到CPU寄存器的本质:把数据的内容,变成自己的上下文(发生线程切换,上下文数据需要被保存回线程,从而变成线程独有的资源 ---- 线程局部储存)

12. 可重入和 线程安全

(一)概念

  1. 线程安全:多个线程并发同一段代码时,不会出现不同的结果。常见对全局变量或者静态变量进行操作,并且没有锁保护的情况下,会出现该问题
  2. 重入:同一个函数被不同的执行流调用,当前一个流程还没有执行完,就有其他的执行流再次进入,我们称之为重入。一个函数在重入的情况下,运行结果不会出现任何不同或者任何问题,则该函数被称为可重入函数,否则,是不可重入函数。

(二)常见的线程不安全的情况

  • 不保护共享变量的函数
  • 函数状态随着被调用,状态发生变化的函数
  • 返回指向静态变量指针的函数
  • 调用线程不安全函数的函数

(三)常见的线程安全的情况

  • 每个线程对全局变量或者静态变量只有读取的权限,而没有写入的权限,一般来说这些线程是安全的
  • 类或者接口对于线程来说都是原子操作
  • 多个线程之间的切换不会导致该接口的执行结果存在二义性

(四)常见不可重入的情况

  • 调用了malloc/free函数,因为malloc函数是用全局链表来管理堆的
  • 调用了标准I/O库函数,标准I/O库的很多实现都以不可重入的方式使用全局数据结构
  • 可重入函数体内使用了静态的数据结构

(五)常见可重入的情况

  • 不使用全局变量或静态变量
  • 不使用用malloc或者new开辟出的空间
  • 不调用不可重入函数
  • 不返回静态或全局数据,所有数据都有函数的调用者提供
  • 使用本地数据,或者通过制作全局数据的本地拷贝来保护全局数据

(六)可重入与线程安全联系

  • 函数是可重入的,那就是线程安全的
  • 函数是不可重入的,那就不能由多个线程使用,有可能引发线程安全问题
  • 如果一个函数中有全局变量,那么这个函数既不是线程安全也不是可重入的

(七)可重入与线程安全区别

  • 可重入函数是线程安全函数的一种
  • 线程安全不一定是可重入的,而可重入函数则一定是线程安全的。
  • 如果将对临界资源的访问加上锁,则这个函数是线程安全的,但如果这个重入函数若锁还未释放则会产生死锁,因此是不可重入的

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

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

相关文章

关于武汉芯景科技有限公司的限流开关芯片XJ6288开发指南(兼容SY6288)

一、芯片引脚介绍 1.芯片引脚 二、系统结构图 三、功能描述 1.EN引脚控制IN和OUT引脚的通断 2.OCB引脚指示状态 3.过流自动断开

C++ [项目] 恶魔轮盘赌

现在才发现C游戏的支持率这么高,那就发几篇吧 零、前情提要 此篇是我与 同学的共创,他负责写人,我负责写机,简称人机, 不过有一点小插曲…… 一、基本介绍 支持Dev-C5.11版本(务必调为英文输入法),基本操作看游戏里的介绍,怎么做的……懒得说,能看懂就看注释,没有…

Vue3结合vue-plugin-hiprint实现自定义打印模板设计与布局

简介 在现代Web应用开发中,打印功能是不可或缺的一部分,尤其是在需要输出标准化文档的场景下。本文将详细介绍如何在Vue3项目中利用vue-plugin-hiprint插件实现一个可定制的打印模板设计器,并通过具体示例来展示其配置与使用方法。 技术栈 …

Python如何导入模块及常见的导入方法

😀前言 在 Python 编程中,模块(Module)是非常重要的工具。它们可以帮助我们将代码进行逻辑分割和复用,从而提高代码的可读性和可维护性。本文将详细介绍如何导入模块、使用常见的导入方法,并简要介绍一些常…

[分享] SQL在线编辑工具(好用)

在线SQL编写工具(无广告) - 在线SQL编写工具 - Web SQL - SQL在线编辑格式化 - WGCLOUD

若依微服务15 - RuoYi-Vue3 实现前端独立运行

正文开始: RuoYi-Vue3 使用 Vue3 Element Plus Vite 技术栈。 GitHub 开源地址:https://github.com/yangzongzhuan/RuoYi-Vue3 本文介绍使用若依提供的在线后端接口,仅启动前端项目并进行界面开发,而无需启动后端服务。 一、克隆…

Vue笔记-浏览器窗口改变时,重新计算表格高度并设置

当窗口大小改变时,你监听 window 对象的 resize 事件,然后在事件处理程序中重新计算表格的高度。在 Vue 中,可以在组件中通过 created 生命周期钩子来添加事件监听器,然后在组件销毁时移除事件监听器。 如下vue代码: …

33 类与对象 · 下

目录 一、构造函数的深入 (一)构造函数的其他特点 (二)使用例 1、Date类与Time类显示写 2、Date类与Time类写一部分 (三)总结 (四)初始化顺序小题目 二、类型转化 &#xff…

Linux Redis查询key与移除日常操作

维护老项目Express node 编写的后端程序、有这么一个方法、没有设置redis过期时间(建议设置过期时间,毕竟登录生产服务器并不是每个人都有权限登录的!!!)。如果变动只能通过登录生产服务器、手动修改… 于…

@Autowired和@Resource的用法与区别

前言: Autowired 和 Resource 来自不同的“父类”,其中 Autowired 是 Spring 定义的注解,而 Resource 是 Java 定义的注解,它来自于 JSR-250(Java 250 规范提案)。当它们的实现类只有一个时,那…

github pages + hugo 搭建静态博客网站

体验地址 1. 起因, 目的: 其实6年前,我就写过这个。 项目代码 博客地址 最近想改写一下。 github 推荐的主题是 Jekyll, 我当时用的就是这个,感觉很麻烦。尤其是文章命名。 新的主题 hugo 用起来还行。 2.过程: 过程记录&am…

代码随想录算法训练营第六天|454四数相加II、 383赎金信、15三数之和、18四数之和

day06 1. 454四数相加II 首先定义 一个unordered_map,key放a和b两数之和,value 放a和b两数之和出现的次数。遍历大A和大B数组,统计两个数组元素之和,和出现的次数,放到map中。定义int变量count,用来统计 …

新电脑Win11家庭中文版跳过联网激活方法(教程)

预装Win11家庭中文版的新电脑,如何跳过联网激活;由于微软限制必须要联网激活,需要使用已有的微软账户登入或者注册新的微软账户后才可以继续开机使用,Win11联网后系统会自动激活。下面介绍一下初次开机初始化电脑时如何跳过联网激…

虚拟滚动列表如何实现?

highlight: a11y-dark 虚拟滚动列表&#xff0c;虚拟滚动的关键在于只渲染当前视口内可见的数据项&#xff0c;而不是一次性渲染所有数据项。这可以显著提高性能&#xff0c;尤其是在处理大量数据时。 以下是一个完整的虚拟滚动列表的示例代码&#xff1a; <!DOCTYPE htm…

RFC2616 超文本传输协议 HTTP/1.1

一、URL-俗称“网址” HTTP 使用 URL(Uniform Resource Locator&#xff0c;统一资源定位符)来定位资源&#xff0c;它是 URI(Uniform Resource Identifier&#xff0c;统一资源标识符)的子集&#xff0c;URL 在 URI 的基础上增加了定位能力 URI 除了包含 URL&#xff0c;还包…

ADC的交流参数

ADC的交流参数是衡量其在处理交流信号时性能的关键指标。一般包括&#xff1a; 1 信噪比&#xff08;Signal-to-Noise Ratio, SNR&#xff09; 这是衡量ADC输出信号中有用信号与噪声水平的比值。信噪比越高&#xff0c;表示ADC的性能越好。 SNR (dB) MaxRMSSignal / RMSNoise…

【你也能从零基础学会网站开发】 SQL Server结构化查询语言数据操作应用--DML篇 select语句数据查询操作详解 今天干货满满!《1024特别篇》

&#x1f680; 个人主页 极客小俊 ✍&#x1f3fb; 作者简介&#xff1a;程序猿、设计师、技术分享 &#x1f40b; 希望大家多多支持, 我们一起学习和进步&#xff01; &#x1f3c5; 欢迎评论 ❤️点赞&#x1f4ac;评论 &#x1f4c2;收藏 &#x1f4c2;加关注 select查询语句…

百度ocr服务自动实现文字识别、图片识别功能

百度ocr服务个人注册使用 介绍一个百度免费的ocr服务&#xff0c;通过调用SDK实现文字、图片识别等功能 1. 复制地址到自己的浏览器打开 https://cloud.baidu.com/doc/OCR/index.html2. 选择【登录】 3. 使用【短信登录】 4. 登录后需要选择【个人刷脸实名认证】 百度官方网…

第5.2章|25考研复试综合素质面试最常见问题50问【附上完整答案】超详细考研机械复试面试经验总结全流程 考研复试调剂问题看这一篇就够了!

接着上一章节的内容我们继续完善这50问的题目。上章节的内容参考这个文章。 第5.1章|25考研复试综合素质面试最常见问题50问【附上完整答案】超详细考研复试面试经验总结全流程 考研复试问题看这一篇就够了!考研复试调剂面试问题-CSDN博客https://blog.csdn.net/weixin_56510…

Linux基础命令(六)之 cut,sort,uniq,tr

目录 一&#xff0c;切割显示cut 参数及其作用 常见用法 二&#xff0c;排序显示sort 参数及其作用 常见用法 三&#xff0c;去重显示uniq 常见用法 四&#xff0c;替换文件中的字符显示tr 参数及其作用 常见用法 一&#xff0c;切割显示cut 用于按列提取文本内容 语…