互斥锁,自旋锁和死锁 一文详解,一网打尽

互斥锁(Mutex)和自旋锁(Spinlock)是两种常见的用于多线程编程中的同步机制,用于确保在多个线程访问共享资源时的协调性和正确性。以下是它们的主要特点和区别:

互斥锁(Mutex)

定义:
互斥锁是一种阻塞锁,当某个线程持有锁时,其他试图获取该锁的线程将被阻塞,直到锁被释放。

特性:

原子性:互斥锁的获取和释放是原子的,确保了在多线程环境下对共享资源的安全访问。
休眠等待:当线程无法获取互斥锁时,它会被操作系统挂起并进入休眠状态,不再消耗CPU资源。
上下文切换:线程被挂起时,操作系统会进行上下文切换,以便其他线程得以执行。
适用场景:
适用于锁被持有时间较长或预计等待时间超过两次线程上下文切换时间的场景。

自旋锁(Spinlock)

定义:
自旋锁是一种非阻塞锁,当线程尝试获取一个被其他线程持有的自旋锁时,该线程会进入忙等待(busy-waiting)状态(一直轮询),即不断地循环检查锁是否可用,而不是被挂起。

特性:

非阻塞:线程在无法获取自旋锁时,不会进入休眠状态,而是持续消耗CPU资源进行忙等待。
无上下文切换:由于线程没有进入休眠状态,因此不会发生上下文切换。
参数限制:为了防止无限循环导致CPU资源耗尽,自旋锁通常有一个参数来限制最大尝试次数。
适用场景:

多核处理器:在多核处理器环境中,如果预计线程等待锁的时间很短,短到比线程两次上下文切换时间要少的情况下,使用自旋锁是划算的。
保持锁时间短:自旋锁比较适用于锁使用者保持锁时间比较短的情况。
中断上下文:如果被保护的共享资源需要在中断上下文访问(包括底半部即中断处理句柄和顶半部即软中断),则必须使用自旋锁。
互斥锁与自旋锁的比较
资源消耗:互斥锁在线程等待时会释放CPU资源,而自旋锁则会持续消耗CPU资源进行忙等待。
上下文切换:互斥锁在线程等待时会导致上下文切换,而自旋锁则没有。
适用场景:互斥锁适用于锁被持有时间较长或预计等待时间较长的场景;自旋锁适用于锁被持有时间较短或预计等待时间较短的场景。
性能:在多核处理器环境中,如果预计等待时间很短,自旋锁的性能可能优于互斥锁;但在单核处理器或预计等待时间较长的情况下,互斥锁的性能可能更好。

死锁(Deadlock)

死锁(Deadlock) 是在并发系统中,两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法向前推进。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。

例如:如果此时有一个线程A,按照先锁a再获得锁b的的顺序获得锁,而在此同时又有另外一个线程B,按照先锁b再锁a的顺序获得锁。这样就会造成的一种互相等待的现象。

死锁发生的原因主要有以下几点:

互斥条件:资源是独占的且排他的使用,进程互斥使用资源,即任一时刻只有一个进程能访问该资源(如打印机、磁带机等)。
请求与保持条件:已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其他进程占有,此时请求进程阻塞,但又对自己已获得的资源保持不放。
不可剥夺条件:进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。
循环等待条件:存在一种进程资源的循环等待链,链中的每一个进程已获得的资源同时被链中下一个进程所请求。

互斥锁中,当锁被释放,等待锁释放的线程是如何知道?

当某个线程持有互斥锁时,其他试图获取该锁的线程将被阻塞,直到锁被释放。一旦锁被释放,被阻塞的线程如何得知锁已可用并继续执行,这涉及到操作系统和互斥锁实现的具体机制。

阻塞队列:

当多个线程试图获取同一把互斥锁,而没有获取到锁的线程会被组织到一个阻塞队列(BlockingQueue)中。
这个阻塞队列是由操作系统或互斥锁实现维护的,用于存储等待锁的线程。

锁释放:

当持有锁的线程完成对共享资源的访问并调用解锁操作时,互斥锁的状态会发生变化,表示锁现在处于可用状态。

通知机制:

一旦锁被释放,操作系统或互斥锁实现会负责通知阻塞队列中的一个或多个线程。
通知的方式通常依赖于底层操作系统的调度机制,比如通过信号、中断或其他同步原语。

线程唤醒:

收到通知的线程会从阻塞状态变为就绪状态(Ready State),等待操作系统的调度。
操作系统会根据其调度策略(如先来先服务、优先级调度等)来决定何时调度该线程到CPU上执行。

重新获取锁:

当线程被操作系统调度到CPU上执行时,它会再次尝试获取互斥锁。
如果此时锁仍然可用(即没有其他线程持有它),则该线程会成功获取锁并继续执行其临界区代码。

防止饥饿:

为了确保公平性,操作系统或互斥锁实现通常会采用某种策略来防止饥饿(Starvation)现象,即确保等待时间较长的线程能够有机会获取到锁。
需要注意的是,具体的实现细节可能因操作系统、编程语言或线程库的不同而有所差异。但总体来说,互斥锁通过阻塞队列、通知机制和线程调度等机制来实现线程间的同步和协调。

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

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

相关文章

curl: (56) Recv failure: 连接被对方重设

目录 问题描述: 解决方案: 1.确认端口未被占用 2.检查 Docker 容器端口映射设置 3. 检查防火墙设置 4. 检查 Docker 网络配置 5. 检查 Docker Daemon 配置 6. 检查 SELinux 或 AppArmor 设置 7. 使用 Docker 命令行工具调试 8. 检查网络和路由设…

基于langchain和向量库微调qwen2-1.5B学习行业专属知识

现在有大量的word文档数据需要让大模型学习形成专业业务领域的知识后对外提供问答服务,以下是基于前问Qwen2-1.5B模型进行langchain RAG向量搜索大模型问答的实现过程。 第一步:原始数据处理 原始word文档数据里面包含了封面、目录、概述、专业知识章节…

网络聚合通信测试--自动化测试脚本

一 网络聚合通信测试 以下测试用例为: 整集群测试,每节点进程数从2开始以2的幂次增加至满核心; 测试常见的通信聚合测试8个条目 二 测试前准备 待测节点已完成OS安装及基础配置待测节点已配置完IP(若存在IB,则需要配置…

第二十二篇——香农第二定律(一):为什么你的网页总是打不开?

目录 一、背景介绍二、思路&方案三、过程1.思维导图2.文章中经典的句子理解3.学习之后对于投资市场的理解4.通过这篇文章结合我知道的东西我能想到什么? 四、总结五、升华 一、背景介绍 看似在将知识,实际是在讲生活和所有;突破边界偶尔…

gitlab 获取指定分支下指定路径文件夹的解决方案

第一步: 获取 accessToken 及你的 项目 id : 获取 accessToken ,点击用户头像进入setting 按图示操作,第 3 步 填写你发起请求的域名。 获取项目 id , 简单粗暴方案 进入 你项目仓库页面后 直接 源码搜索 project_id, value 就…

【神经网络】基于CNN(卷积神经网络)构建猫狗分类模型

文章目录 解决问题数据集探索性数据分析数据预处理数据集分割数据预处理 构建模型并训练构建模型训练模型 结果分析与评估模型保存结果预测经验总结 解决问题 针对经典猫狗数据集,基于卷积神经网络,构建猫狗二元分类模型,使用数据集进行参数…

怎么提取视频中的音频?别错过这6个音频提取方法了!(全新)

您是否曾经发现过一个音乐很棒的视频,并想从视频中提取音频?如今,关于提取mp4视频中的音频需求越来越常见。例如,您可能想从mp4格式的电影中提取音频,将音乐用作手机铃声,或在自己的视频项目中使用视频中的…

[Qt] Qt Creator 编码警告:warning:C4819

Qt项目使用VC(2019 64bit)编译器出现此错误。 warning:C4819:该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为Unicode格式以防止数据丢失。(可能这个警告内容也会在Qt Creator 中乱码) 如…

Matlab只选取自己需要的数据画图

在Matlab作图的时候,经常会在同一个坐标系中作很多数据的图,如下图所示: 这就会导致不同数据所作的线会重叠在一起,不利于数据分析。如果只想对比几个数据的趋势,直接修改代码太过麻烦,可通过Matlab的绘图…

【C语言】数组参数和指针参数详解

在写代码的时候难免要把【数组】或者【指针】传给函数&#xff0c;那函数的参数该如何设计呢&#xff1f; 1 一维数组传参 #include <stdio.h> void test(int arr[])//ok? {} void test(int arr[10])//ok? {} void test(int* arr)//ok? {} void test2(int* arr[20])…

Java毕业设计 基于SSM助学贷款管理系统

Java毕业设计 基于SSM助学贷款管理系统 SSM 助学贷款管理系统 功能介绍 学生&#xff1a;登录 修改密码 学生信息 贷款项目信息 申请贷款 留言信息 公告 学校负责人&#xff1a;登录 修改密码 学生管理 学校负责人信息 贷款项目 贷款申请审批 留言信息 公告 银行负责人&…

Linux中nginx.conf如何配置【搬代码】

Nginx 是一个独立的软件。 它是一款高性能的 Web 服务器、反向代理服务器和负载均衡器等&#xff0c;具有强大的功能和广泛的应用场景。它通常需要单独进行安装和配置来发挥其作用。 下载网址&#xff1a;http://nginx.org/en/download.html nginx.conf写法&#xff1a; #配置…

鸿蒙实现金刚区效果

前言&#xff1a; DevEco Studio版本&#xff1a;4.0.0.600 所谓“金刚区"是位于APP功能入口的导航区域&#xff0c;通常以“图标文字”的宫格导航的形式出现。之所以叫“金刚区”&#xff0c;是因为该区域会随着业务目标的改变&#xff0c;展示不同的功能图标&#xff…

PostgreSQL源码分析——CREATE DATABASE

这里我们分析一下在PostgreSQL中创建数据库的源码&#xff0c;在分析源码之前&#xff0c;最好先阅读《PostgreSQL指南内幕探索》的第一章&#xff0c;数据库集簇、数据库和数据表&#xff0c;弄清其空间布局&#xff0c;理解PG中&#xff0c;数据库、表、元组是怎么布局的。通…

Collections.sort()方法总结

Collections.sort()方法总结 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天我们来探讨 Java 中的 Collections.sort() 方法。这个方法是 Java 集合框架中的…

C# —— 字符串的相关属性和方法

string 属于特殊的引用类型 字符串创建的三种方式 string s "路飞";//自变量定义方式 字符串当中如果要有特殊的符号,使用\进行转义 \t tab \n 换行 \r return键 s "123\rb\tc\nd,想在字符串当中展示引号,需要使用\"进行转义,想输入一个右斜杠\\,想显…

下载工程resources目录下的模板excel文件

一、添加依赖 <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>5.1.0</version> </dependency> 二、编写接口 GetMapping("/downloadTemplate")public void downlo…

C++ 70 之 类模版中的成员函数,在类外实现

#include <iostream> #include <string> using namespace std;template<class T1, class T2> class Students10{ public:T1 m_name;T2 m_age;Students10(T1 name, T2 age); // 类内声明 类外实现// {// this->m_name name;// this->m_age …

CCAA质量管理【学习笔记】​​ 备考知识点笔记(六)质量改进系统方法与工具

第七节 质量改进系统方法与工具 1 质 量 改 进 方 法 概 述 可以说几乎每种质量管理领域的方法与工具都可以用于质量改进&#xff0c;但是一个组织在改进的整体推进中&#xff0c;往往不是采用单一的方法&#xff0c;会涉及多种改进的工具和手段&#xff0c;并依据一定的模式…

鸿蒙实现自定义Tabbar样式,显示数字红点提示

前言&#xff1a; DevEco Studio版本&#xff1a;4.0.0.600 Tabs的链接参考&#xff1a;OpenHarmony Tabs TabContent的链接参考&#xff1a;OpenHarmony TabContent 通过查看链接参考我们知道可以通过TabContent的tabBar来实现自定义TabBar样式&#xff08;CustomBuilder&…