当前位置: 首页 > news >正文

Linux锁的使用

一、临界资源与临界区

多线程会共享例如全局变量等资源,我们把会被多个执行流访问的资源称为临界资源,我们是通过代码访问临界资源的,而我们访问临界资源的那部分代码称为临界区。

实现一个抢票系统

只有一个线程抢票时

#include <iostream>
#include <vector>
#include <unistd.h>#include "Thread.hpp"int num = 10000; std::string GetThreadName()
{static int num = 1;char name[64];snprintf(name, sizeof(name), "thread-%d", num++);return name;
}void Ticket(std::string name)
{while(true){if(num > 0){usleep(1000);printf("%s get ticket: %d\n", name.c_str(), num);num--;}else{break;}}
}int main()
{std::string name1 = GetThreadName();Thread<std::string> t1(name1, Ticket, name1);t1.Start();t1.Join();return 0;
}

正常输出,最终票数为0时退出。

但是当我们启动多个线程同时抢票时,num就是临界资源,使用num的那部分代码就是临界区

#include <iostream>
#include <vector>
#include <unistd.h>#include "Thread.hpp"int num = 10000; std::string GetThreadName()
{static int num = 1;char name[64];snprintf(name, sizeof(name), "thread-%d", num++);return name;
}void Ticket(std::string name)
{while(true){if(num > 0){usleep(1000);printf("%s get ticket: %d\n", name.c_str(), num);num--;}else{break;}}
}int main()
{std::string name1 = GetThreadName();Thread<std::string> t1(name1, Ticket, name1);std::string name2 = GetThreadName();Thread<std::string> t2(name2, Ticket, name2);std::string name3 = GetThreadName();Thread<std::string> t3(name3, Ticket, name3);std::string name4 = GetThreadName();Thread<std::string> t4(name4, Ticket, name4);t1.Start();t2.Start();t3.Start();t4.Start();t1.Join();t2.Join();t3.Join();t4.Join();return 0;
}

可以看到出现了0和负数的票数,这是因为当票数只剩1时,有多个执行流在同一时间通过了if判断,使得能继续进行减票操作。

vs下自减操作的反汇编,分为三步:先从内存拿数据,再把数据减1,最后把数据拷贝到内存

多个执行流同时访问临界资源例如自减操作,由于--操作不是原子性的(我们认为一条汇编指令是原子性的,是不会被中断的。但--操作转为汇编指令后,需要多条指令才能完成),当--操作执行到一半切换到其他线程会导致数据不一致的问题。这种情况下需要通过锁把临界区保护起来,每次只让一个执行流访问临界资源,避免数据不一致问题。

互斥:任何时刻,互斥保证有且只有一个执行流进入临界区,访问临界资源,通常对临界资源起保护作用。

原子性:不会被任何调度机制打断的操作,该操作只有两态,要么完成,要么未完成。

二、使用锁的方法

1.创建锁

如果定义一个全局的锁,直接使用pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER用宏初始化。

如果定义一个局部锁,要使用pthread_mutex_init方法创建,参数attr设为nullptr

2.加锁解锁

使用pthread_mutex_lock加锁,传递锁的地址,

解锁用pthread_mutex_unlock

当我们使用锁后,就能保证每次只有一个执行流能访问临界资源。

#include <iostream>
#include <vector>
#include <unistd.h>#include "Thread.hpp"int num = 10000;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; //定义一个全局锁std::string GetThreadName()
{static int num = 1;char name[64];snprintf(name, sizeof(name), "thread-%d", num++);return name;
}void Ticket(std::string name)
{while(true){pthread_mutex_lock(&mutex); //加锁if(num > 0){usleep(1000);printf("%s get ticket: %d\n", name.c_str(), num);num--;pthread_mutex_unlock(&mutex); //解锁}else{pthread_mutex_unlock(&mutex); //解锁break;}}
}int main()
{std::string name1 = GetThreadName();Thread<std::string> t1(name1, Ticket, name1);std::string name2 = GetThreadName();Thread<std::string> t2(name2, Ticket, name2);std::string name3 = GetThreadName();Thread<std::string> t3(name3, Ticket, name3);std::string name4 = GetThreadName();Thread<std::string> t4(name4, Ticket, name4);t1.Start();t2.Start();t3.Start();t4.Start();t1.Join();t2.Join();t3.Join();t4.Join();return 0;
}

结果正常,但是速度慢了很多,因为要不断申请锁和释放锁

加锁解锁的过程是安全的

三、可重入和线程安全

1.概念

线程安全:多个线程并发同一段代码时,不会出现不同的结果。常见对全局变量或者静态变量进行操作, 并且没有锁保护的情况下,会出现该问题。

重入:同一个函数被不同的执行流调用,当前一个流程还没有执行完,就有其他的执行流再次进入,我们称之为重入。一个函数在重入的情况下,运行结果不会出现任何不同或者任何问题,则该函数被称为可重入函数,否则,是不可重入函数。

2.常见的线程不安全的情况

1.不保护共享变量的函数

2.函数状态随着被调用,状态发生变化的函数

3.返回指向静态变量指针的函数

4.调用线程不安全函数的函数

3.常见的线程安全的情况

1.调用了malloc/free函数,因为malloc函数是用全局链表来管理堆的

2.调用了标准I/O库函数,标准I/O库的很多实现都以不可重入的方式使用全局数据结构

3.可重入函数体内使用了静态的数据结构

4.常见可重入的情况

1.不使用全局变量或静态变量

2.不使用用malloc或者new开辟出的空间

3.不调用不可重入函数不返回静态或全局数据,所有数据都有函数的调用者提供

4.使用本地数据,或者通过制作全局数据的本地拷贝来保护全局数据

5.可重入与线程安全联系

1.函数是可重入的,那就是线程安全的

2.函数是不可重入的,那就不能由多个线程使用,有可能引发线程安全问题

3.如果一个函数中有全局变量,那么这个函数既不是线程安全也不是可重入的。

6.可重入与线程安全区别

1.可重入函数是线程安全函数的一种

2.线程安全不一定是可重入的,而可重入函数则一定是线程安全的。

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

四、死锁

死锁是指在一组进程中的各个进程均占有不会释放的资源,但因互相申请被其他进程所站用不会释放的资源而处于的一种永久等待状态。

1.死锁四个必要条件

1.互斥条件:一个资源每次只能被一个执行流使用

2.请求与保持条件:一个执行流因请求资源而阻塞时,对已获得的资源保持不放

3.不剥夺条件: 一个执行流已获得的资源,在末使用完之前,不能强行剥夺

4.循环等待条件: 若干执行流之间形成一种头尾相接的循环等待资源的关系

2.避免死锁

1.破坏死锁的四个必要条件

2.加锁顺序一致

3.避免锁未释放的场景

4.资源一次性分配

3.避免死锁算法

1.死锁检测算法

2.银行家算法

一个锁会造成死锁吗?

答案是会的,当一个线程申请完一个锁,访问完临界资源后,接下来该释放锁了,但是代码却写成了加锁,这就会导致死锁问题。

相关文章:

Linux锁的使用

一、临界资源与临界区 多线程会共享例如全局变量等资源&#xff0c;我们把会被多个执行流访问的资源称为临界资源&#xff0c;我们是通过代码访问临界资源的&#xff0c;而我们访问临界资源的那部分代码称为临界区。 实现一个抢票系统 只有一个线程抢票时 #include <ios…...

go语言学习--2.函数

目录 1.函数分类 2.函数的声明和定义 3.函数传参 4.函数返回值 5.递归调用 为完成某一功能的程序指令(语句)的集合&#xff0c;称为函数。 1.函数分类 在Go语言中&#xff0c;函数是第一类对象&#xff0c;我们可以将函数保持到变量中。函数主要有具名和匿名之分&#x…...

[安卓逆向]常见调试和反调试及解决方案

写在前面 我们在逆向软件时难免会遇到一些反调试策略&#xff0c;这篇文章就来详细总结下&#xff0c;现阶段比较流行的几种反调试策略及解决方案。 特定文件检测 反调试功能&#xff1a; 通过检测文件方式&#xff0c;检测android_server文件是否存在设备中的指定目录/data/l…...

uni-app(H5)论坛 | 社区 表情选择 UI组件

项目源码请移步&#xff1a;bbs 效果 实现思路 表情切换 人物、动物、小黄人不同表情之间的切换实际就是组件的切换 emoji表情 emoji表情本身就是一种字符 如需其他emoji表情可参考 EmojiAll中文官方网站 需要注意的就是数据库的存储格式需要支持emoji表情&#xff0c;我项…...

基于SpringBoot+vue的在线商城系统+论文+免费远程调试

基于SpringBootvue的在线商城系统034(含源码 数据库文档免费送&#xff09; 开发系统:Windows10 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工具:IDEA 数据库版本: mysql8.0 数据库可视化工具: navicat 服务器: SpringBoot自带 apache tomcat 主要技术: Java,Springb…...

mac中创建的证书提示是无效或者是证书不受信任的解决办法

mac中创建的证书提示是无效或者是证书不受信任的解决办法 原因&#xff1a; &#xff08;1&#xff09;可能是由于自己的误删除将Apple worldwide Developer Relatioans Certification Authority删除掉了 (2) 由于签发的认证的证书到期了 &#xff08;3&#xff09;其它未知原…...

LangChain Demo | 如何调用stackoverflow并结合ReAct回答代码相关问题

背景 楼主决定提升与LLM交互的质量&#xff0c;之前是直接prompt->answer的范式&#xff0c;现在我希望能用上ReAct策略和能够检索StackOverflow&#xff0c;让同一款LLM发挥出更大的作用。 难点 1. 怎样调用StackOverflow step1 pip install stackspi step 2 from la…...

老子云、AMRT3D、眸瑞科技

老子云概述 老子云3D可视化快速开发平台&#xff0c;集云压缩、云烘焙、云存储云展示于一体&#xff0c;使3D模型资源自动输出至移动端PC端、Web端&#xff0c;能在多设备、全平台进行展示和交互&#xff0c;是全球领先、自主可控的自动化3D云引擎。 平台架构 平台特性 1、基…...

2023.4.7 机器学习周报

目录 引言 Abstract 文献阅读 1、题目 2、引言 3、过去方案和Motivation 4、Segment Anything模型 5、创新点 6、实验过程 7、实验结果 1、评价绩效 2、检测评价 3、跟踪评价 8、 结论 总结 引言 本周阅读了一篇关于高效的任意分割模型的文献&#xff0c;用于自…...

如何将平板或手机作为电脑的外接显示器?

先上官网链接&#xff1a;ExtensoDesk 家里有一台华为平板&#xff0c;自从买回来以后除了看视频外&#xff0c;基本没什么作用&#xff0c;于是想着将其作为我电脑的第二个屏幕&#xff0c;提高我学习办公的效率&#xff0c;废物再次利用。最近了解到华为和小米生态有多屏协同…...

Tuxera NTFS for Mac2023绿色免费版 免费的ntfs for mac 免费读写硬盘U盘工具

Tuxera NTFS 2023 Mac免费版是款适合Mac用户使用的磁盘读写工具。Tuxera NTFS 2023 Mac可以很好的帮助用户在Mac上打开、编辑、复制、移动或删除存储在Windows NTFS格式的USB驱动器上的文件。并且Tuxera NTFS 2023 Mac还可以无阻碍地使用各种文件系统磁盘&#xff0c;还能解决磁…...

使用阿里云试用Elasticsearch学习:3.6 处理人类语言——同义词

词干提取是通过简化他们的词根形式来扩大搜索的范围&#xff0c;同义词 通过相关的观念和概念来扩大搜索范围。 也许没有文档匹配查询 “英国女王“ &#xff0c;但是包含 “英国君主” 的文档可能会被认为是很好的匹配。 用户搜索 “美国” 并且期望找到包含 美利坚合众国 、…...

018——红外遥控模块驱动开发(基于HS0038和I.MX6uLL)

目录 一、 模块介绍 1.1 简介 1.2 协议 二、 驱动代码 三、 应用代码 四、 实验 五、 程序优化 一、 模块介绍 1.1 简介 红外遥控被广泛应用于家用电器、工业控制和智能仪器系统中&#xff0c;像我们熟知的有电视机盒子遥控器、空调遥控器。红外遥控器系统分为发送端和…...

【学习心得】Python中的queue模块使用

一、Queue模块的知识点思维导图 二、Queue模块常用函数介绍 queue模块是内置的&#xff0c;不需要安装直接导入就可以了。 &#xff08;1&#xff09;创建一个Queue对象 import queue# 创建一个队列实例 q queue.Queue(maxsize20) # 可选参数&#xff0c;默认为无限大&am…...

ubuntu-server部署hive-part4-部署hive

参照 https://blog.csdn.net/qq_41946216/article/details/134345137 操作系统版本&#xff1a;ubuntu-server-22.04.3 虚拟机&#xff1a;virtualbox7.0 部署hive 下载上传 下载地址 http://archive.apache.org/dist/hive/ apache-hive-3.1.3-bin.tar.gz 以root用户上传至…...

贪心算法|135.分发糖果

力扣题目链接 class Solution { public:int candy(vector<int>& ratings) {vector<int> candyVec(ratings.size(), 1);// 从前向后for (int i 1; i < ratings.size(); i) {if (ratings[i] > ratings[i - 1]) candyVec[i] candyVec[i - 1] 1;}// 从后…...

c# wpf template itemtemplate+ListBox

1.概要 2.代码 <Window x:Class"WpfApp2.Window7"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d"http://schemas.microsoft.com/expression/blend/…...

关于JVM-三色标记算法剖析

相关系列 深入理解JVM垃圾收集器-CSDN博客 深入理解JVM垃圾收集算法-CSDN博客 深入理解jvm执行引擎-CSDN博客 jvm优化原则-CSDN博客 jvm流程图-CSDN博客 三色标记产生的原因&#xff1f; 在并发标记的过程中&#xff0c;因为标记期间应用线程还在继续跑&#xff0c;对象间的引…...

怎么看有没有装python

windows系统&#xff0c;运行——cmd&#xff0c;进入dos窗口&#xff0c;输入python&#xff0c;安装成功的话可以看到版本信息并进入编程模式。 如下图&#xff08;我安装的版本是python 3.5.1&#xff09;&#xff1a;...

VS CODE环境安装和hello world

SAP UI5 demo walkthrough tutorial step1 hello word 首先要安装nodejs&#xff0c;然后才能执行下面的操作 nodejs vscode 安装ui5 npm install --global ui5/cli报错解决: idealTree:npm: sill idealTree buildDeps 这个信息说明npm正在构建&#xff0c;如一直停留在这个…...

Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误

HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误&#xff0c;它们的含义、原因和解决方法都有显著区别。以下是详细对比&#xff1a; 1. HTTP 406 (Not Acceptable) 含义&#xff1a; 客户端请求的内容类型与服务器支持的内容类型不匹…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)

HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...

模型参数、模型存储精度、参数与显存

模型参数量衡量单位 M&#xff1a;百万&#xff08;Million&#xff09; B&#xff1a;十亿&#xff08;Billion&#xff09; 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的&#xff0c;但是一个参数所表示多少字节不一定&#xff0c;需要看这个参数以什么…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器

——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的​​一体化测试平台​​&#xff0c;覆盖应用全生命周期测试需求&#xff0c;主要提供五大核心能力&#xff1a; ​​测试类型​​​​检测目标​​​​关键指标​​功能体验基…...

《通信之道——从微积分到 5G》读书总结

第1章 绪 论 1.1 这是一本什么样的书 通信技术&#xff0c;说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号&#xff08;调制&#xff09; 把信息从信号中抽取出来&am…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)

设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile&#xff0c;新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

基于TurtleBot3在Gazebo地图实现机器人远程控制

1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...

从“安全密码”到测试体系:Gitee Test 赋能关键领域软件质量保障

关键领域软件测试的"安全密码"&#xff1a;Gitee Test如何破解行业痛点 在数字化浪潮席卷全球的今天&#xff0c;软件系统已成为国家关键领域的"神经中枢"。从国防军工到能源电力&#xff0c;从金融交易到交通管控&#xff0c;这些关乎国计民生的关键领域…...

【LeetCode】算法详解#6 ---除自身以外数组的乘积

1.题目介绍 给定一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O…...

深度剖析 DeepSeek 开源模型部署与应用:策略、权衡与未来走向

在人工智能技术呈指数级发展的当下&#xff0c;大模型已然成为推动各行业变革的核心驱动力。DeepSeek 开源模型以其卓越的性能和灵活的开源特性&#xff0c;吸引了众多企业与开发者的目光。如何高效且合理地部署与运用 DeepSeek 模型&#xff0c;成为释放其巨大潜力的关键所在&…...