Linux 线程同步——信号量

news2024/11/22 6:18:40

一、线程同步的概念

这里的同步就是对程序的执行进行控制,因为如果不进行控制就会出现错误的问题,这里的控制是为了保证程序的正确性。

线程同步指的是当一个线程在对某个临界资源进行操作时,其他线程都不可以对这个资源进行操作,直到该线程完成操作, 其他线程才能操作,也就是协同步调,让线程按预定的先后次序进行运行。

线程同步的方法有四种:互斥锁、信号量、条件变量、读写锁。

二、信号量

1.信号量的应用引入示例

代码如下:

在这里插入图片描述

运行结果:

第一次运行结果:
在这里插入图片描述

第二次运行结果:

在这里插入图片描述

由结果可以看出,并不是每个线程每次输出的都是5000,而是会有低于5000的情况,这是因为可能会有两个线程在并行运行的时候同时去访问变量g_count,两个线程拿到的g_count的值是相同的,同时执行g_count++,这样就会导致两个线程并不会把g_count的值分别加两次,属于两个线程同时对g_count加1,相当于g_count只加了一次,就会使我们少一个数字。

使用信号量解决上面这一问题。

2.信号量函数

线程中使用的基本信号量函数有4个。

(1)sem_init()初始化信号量

在这里插入图片描述

参数解释:

第一个参数sem:信号量的变量。

第二个参数pshared:控制信号量的类型,如果其值为0,就表示整个信号量是当前进程的局部信号量,不让该信号量在多个进程之间共享。否则这个信号量就可以在多个进程之间共享。一般设置为0,不让信号量在进程间共享。

第三个参数value:无符号类型,设置信号量的初始值。

(2)sem_wait()P操作

在这里插入图片描述

参数解释:

参数sem:传所定义的信号量的地址。
该将对该信号量执行P(-1)操作。

(3)sem_post()V操作

在这里插入图片描述

参数解释:

参数sem:传所定义的信号量的地址。
该函数将对该信号量执行V(+1)操作。

(4)sem_destroy()销毁信号量

在这里插入图片描述

参数解释:

参数sem:传所定义的信号量的地址。

该函数将销毁所指向的信号量。

3.信号量的具体应用

将上述示例中的代码修改之后如下:

在这里插入图片描述

运行结果:

在这里插入图片描述

此时,在每一个线程中都加入了信号量,在g_count++之前进行p操作获取资源,如果获取不到则说明另外四个线程中的其中一个正在使用信号量,使用完之后执行了v操作,这时当前这个线程才可以成功执行p操作,才可以执行g_count++操作,执行完g_count++操作之后再执行v操作释放资源,此时其他线程才可以使用信号量。这样就避免了两个或者多个线程同时获取g_count的值进行++操作,然后导致g_count的值只被加了一次。这样就会输出正确的g_count在5个线程中加了1000次之后的值5000。

三、互斥锁

1.互斥锁的概念

互斥锁也称为互斥量,互斥锁是多线程程序中的同步访问方法的一种。互斥锁允许程序员锁住某一个对象,使得每次只能有一个线程访问它。为了控制对关键代码的访问,必须在进入这段代码之前设置一个互斥锁,然后在完成操作之后解锁它。

【注意】加锁会使程序的性能下降,但是可以保证程序的正确性。

2.互斥锁函数

(1)pthread_mutex_init()初始化互斥锁

在这里插入图片描述

参数解释:

第一个参数mutex:传入互斥锁变量的地址。
第二个参数mutexattr:互斥锁的属性,一般传NULL。

(2)pthread_mutex_lock()加锁

这个函数又可能发生阻塞,如果发现锁已经被加上了,这个时候就加锁不成功,就会发生阻塞。

在这里插入图片描述

参数解释:

参数mutex:传入所定义的互斥锁变量的地址。为该互斥锁加锁。

(3)pthread_mutex_unlock()解锁

在这里插入图片描述

参数解释:

参数mutex:传入所定义的互斥锁变量的地址。为该互斥锁解锁。

(4)pthread_mutex_destory()销毁锁

在这里插入图片描述

参数解释;

参数mutex:传入所定义的互斥锁变量的地址。销毁该互斥锁。

3.互斥锁的应用

代码如下:

在这里插入图片描述

运行结果:

在这里插入图片描述

在这个程序中,互斥锁的使用和信号量一样,在每一个线程中都加入了互斥锁,在g_count++之前执行加锁操作,使每次只能有一个线程访问变量g_count,如果访问不到则说明已经被别的线程加锁,这时当前这个线程不可以对锁着的变量g_count进行++操作,会发生阻塞,只有等别的线程对变量g_count解锁之后,当前的线程才可以成功执行加锁操作,才可以执行g_count++操作,执行完g_count++操作之后再执行解锁操作,此时其他线程才可以继续对变量g_count进行加锁操作。这样就避免了两个或者多个线程同时获取g_count的值进行++操作,然后导致g_count的值只被加了一次。这样就会输出正确的g_count在5个线程中加了1000次之后的值5000。

四、读写锁

1.读写锁的引入

但是有些场景,加锁并不是为了去修改数据,而是为了读取数据。比如说有一些线程要读取数据,有一些线程要修改数据,如果一个线程想读取,另外一个线程想修改,那么这两个线程肯定是不能同时执行的;如果两个线程都想修改数据,那么这两个线程也不可以同时执行;但是如果两个线程都想读取数据,这时这两个线程就可以同时执行。

而在程序中我们大量的需求可能只是读取数据,偶尔会修改数据。对于互斥锁来说,一旦加锁,就知道当前那个线程读取数据,别的线程都不可以读取数据,这样的话比较繁琐。如果使用读写锁,就可以在一定程度上把力度分的更细一点,这样的话读取数据的时候,多个线程可以同时执行,同时读取数据。如果要修改数据的话,就不可以,就会阻塞,必须要等别的线程读取完数据之后才可以修改数据。

2.读写锁函数

(1)pthread_rwlock_init()初始化读写锁

在这里插入图片描述

(2)pthread_rwlock_rddlock()加读锁

在这里插入图片描述

(3)pthread_rwlock_wrlock()加写锁

在这里插入图片描述

(4)pthread_rwlock_unlock()解锁

无论哪个锁,都可以解

在这里插入图片描述

(5)pthread_rwlock_destroy()销毁锁

在这里插入图片描述

3.读写锁的使用

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

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

相关文章

json文件读取数据报错 AttributeError: ‘str‘ object has no attribute ‘items‘

trans_width_table表如下: {frozenset({2}): {3: 250, 2.5: 100, 1.5: 25, 2: 50, 1.8: 50, 2.75: 200, 5: 350, 4: 350, 2.3: 100, 4.5: 350, 3.5: 300}, frozenset({1, 3, 4, 5}): {2.5: 75, 2.75: 100, 1.5: 25, 4: 300, 3.5: 200, 4.5: 300, 3: 100, 5: 300, 2…

沁恒ch32V208处理器开发(六)BLE开发

目录 概述任务初始化任务的调度执行TMOS 处理事件方法 概述 CH32V 系列是基于青稞 32 位 RISC-V 设计的工业级通用微控制器,片上集成 2Mbps 低功耗蓝牙通讯模块,支持低功耗蓝牙 BLE5.x,低功耗蓝牙协议栈以及应用均基于 TMOS(Task…

光电比赛小车寻宝【1】--循迹策略

2023光电比赛总结:主要功能实现了,就是视频没做好,落选了非常的遗憾,也有很多的不甘心,也可以作为最后摆烂的惩罚吧,在这里总结一下经验教训。整体感觉时间不是非常充分,因为得到比赛的消息后突…

Linux之管理逻辑卷

目录 管理逻辑卷 认识LInux逻辑卷 LVM基本概念 部署逻辑卷 常用LVM部署命令 案例 管理与调整LVM卷 1.扩展卷组——添加/dev/nvme0n2p4物理卷到vg01中 2.在线扩展逻辑卷 管理逻辑卷 逻辑卷管理器是Linux 系统用于对硬盘分区进行管理的一种机制, 理论性较强 &…

安装搭建私有仓库 Harbor

目录 一. 准备环境 1.1安装 Docker 1.2安装 Docker Compose 二. 下载 Harbor 安装包 三. 解压安装包 四. 配置 Harbor 五. 安装 Harbor 六. 访问 Harbor 七. 创建项目、用户和角色 一. 准备环境 确保您的服务器满足 Harbor 的系统要求。最低要求是至少 2 核 CPU、4GB…

【沁恒蓝牙mesh】CH58x串口环形FIFO数据处理

本文章主要针对沁恒科技的CH58x芯片,以 BLE_UART 工程为依托,介绍串口数据的接收与处理。 该工程中 串口数据的处理用到了环形FIFO机制,可作为其他开发工具 📋 个人简介 💖 作者简介:大家好,我…

【LLM数据篇】预训练数据集+指令生成sft数据集

note 在《Aligning Large Language Models with Human: A Survey》综述中对LLM数据分类为典型的人工标注数据、self-instruct数据集等优秀的开源sft数据集:alpaca_data、belle、千言数据集、firefly、moss-003-sft-data多轮对话数据集等 文章目录 note构造指令实例…

k8s扩缩容与滚动更新

使用kubectl run创建应用 kubectl run kubernetes-bootcamp \> --imagedocker.io/jocatalin/kubernetes-bootcamp:v1 \> --port8080 端口暴露出去 kubectl expose pod kubernetes-bootcamp --type"NodePort" --port 8080 使用kubectl create创建应用 kubect…

该产品与此版 VMware Workstation 不兼容,因此无法使用

目录 VMware虚拟机开机报错 解决错误 VMware虚拟机开机报错 配置文件“D:\Users\tyn\Documents\Virtual Machines\Ubuntu16 的克隆\Ubuntu16 的克隆.vmx”是由 VMware 产品创建,但该产品与此版 VMware Workstation 不兼容,因此无法使用。 无法打开配…

VMware 虚拟机三种网络模式详解

文章目录 前言桥接模式(Bridged)桥接模式特点: 仅主机模式 (Host-only)仅主机模式 (Host-only)特点: NAT网络地址转换模式(NAT)仅主机模式 (Host-only)特点: 前言 很多同学在初次接触虚拟机的时候对 VMware 产品的三种网络模式不是很理解,本文就 VMware 的三种网络模式进行说明…

线上异常的处理

一、线上问题的排查 进程ID 简称为PID free -m 查看内存使用情况 iostat 查看磁盘读写活动情况 netstat 查看网络连接情况 df -h 查看磁盘空间使用情况 du -sh 查看文件大小情况 1.1、top 命令查看CPU占用情况 top -n num 查看CPU占用最高的num个进程top -Hp PID 或 top -H -p…

Vulnhub系列靶机--- Hackadmeic.RTB1

系列:Hackademic(此系列共2台) 难度:初级 信息收集 主机发现 netdiscover -r 192.168.80.0/24端口扫描 nmap -A -p- 192.168.80.143访问80端口 使用指纹识别插件查看是WordPress 根据首页显示的内容,点击target 点击…

Java-类与对象(上)

什么是面向对象 Java是一门纯面向对象的语言(Object Oriented Program,简称OOP),在面向对象的世界里,一切皆为对象。 面向对象是解决问题的一种思想,主要依靠对象之间的交互完成一件事情。 以面向对象方式来进行处理,就…

宏病毒的实践

一、实验目的: 1、了解梅丽莎宏病毒基本概念 2、自己实验梅丽莎宏病毒 二、预备知识: 1.什么是word宏 宏是一个批处理程序命令,正确地运用它可以提高工作效率。微软的office软件运行用户自己编写,叫VBA的脚本来增加其灵活性&…

12. 登录拦截器

由于论坛中的所有功能接口都需要在用户登录的情况下才能访问,所以要做统一的登录身份校验。 1. 在 interceptor 包下创建 LoginInterceptor Component // 交给 Spring 管理 public class LoginInterceptor implements HandlerInterceptor {// 从配置文件中读取配…

ChatGPT和Claude的能力全测评

创造性思维/语言 提示:“写一首 4 行诗,每行只有 3 个词,描写重庆” ChatGPT写诗👇 Claude写诗👇 仁者见仁,您怎么看谁更强? 提示: "如果你随机选择这个问题的答案,…

postgresql 的递归查询

postgresql 的递归查询功能很强大,可以实现传统 sql 无法实现的事情。那递归查询的执行逻辑是什么呢?在递归查询中,我们一般会用到 union 或者 union all,他们两者之间的区别是什么呢? 递归查询的执行逻辑 递归查询的…

⛳ TCP 协议面试题

目录 ⛳ TCP 协议面试题🐾 一、为什么关闭连接的需要四次挥⼿,⽽建⽴连接却只要三次握⼿呢?🏭 二、为什么连接建⽴的时候是三次握⼿,可以改成两次握⼿吗?👣 三、为什么主动断开⽅在TIME-WAIT状态…

shell 简单且常用的几种

目录 一、配置环境的shell脚本 二、系统资源脚本 一、要求 二、脚本内容 三、脚本解析 四、赋权并验证 一、配置环境的shell脚本 systemctl stop firewalld systemctl disable firewalld systemctl stop NetworkManager systemctl disable NetworkManager setenforce…

动物IT

动物是地球上最丰富和多样化的生物群体之一。它们包括鱼类、鸟类、爬行动物、两栖动物和哺乳动物等各种类型。动物在地球上有着不同的生态角色和生活习性。 动物对于维持生态平衡和生态系统的稳定性至关重要。它们在食物链中扮演着重要的角色,通过捕食和被捕食来保…