计算机操作系统学习笔记(8)——死锁

简介: 计算机操作系统学习笔记(8)——死锁

一、死锁

多线程为了防止竞争共享资源⽽导致数据错乱,都会在操作共享资源之前加上互斥锁,只有成功获得到锁的线程,才能操作共享资源,获取不到锁的线程就只能等待,直到锁被释放。


当两个线程为了保护两个不同的共享资源⽽使⽤了两个互斥锁,那应⽤不当的时候,可能会造成两个线程都在等待对⽅释放锁,这种情况就是发⽣了死锁。


说白了就是我有你需要的东西,你也有我需要的东西,但是我们2个谁都不肯放手,就导致了死锁


死锁只有同时满⾜以下四个条件才会发⽣:

互斥条件;
持有并等待条件;
不可剥夺条件;
环路等待条件;

互斥条件

互斥条件是指多个线程不能同时使⽤同⼀个资源。

如果线程 A 已经持有的资源,不能再同时被线程 B 持有,如果线程 B 请求获取线程 A 已经占⽤的资源,那线程 B 只能等待,直到线程 A 释放了资源。


持有并等待条件

持有并等待条件是指,当线程 A 已经持有了资源 1,⼜想申请资源 2,⽽资源 2 已经被线程C 持有了,所以线程 A 就会处于等待状态,但是线程 A 在等待资源 2 的同时并不会释放⾃⼰已经持有的资源 1


不可剥夺条件

不可剥夺条件是指,当线程已经持有了资源 ,在⾃⼰使⽤完之前不能被其他线程获取,线程B 如果也想使⽤此资源,则只能在线程 A 使⽤完并释放后才能获取。


环路等待条件

环路等待条件指都是,在死锁发⽣的时候,两个线程获取资源的顺序构成了环形链。


二、避免死锁问题的发⽣

避免死锁问题就只需要四个条件破环其中⼀个条件就可以了

常⻅的并且可⾏的就是使⽤资源有序分配法,来破坏环路等待条件。

什么是资源有序分配法呢?


线程 A 和 线程 B 获取资源的顺序要⼀样,当线程 A 是先尝试获取资源 A,然后尝试获取资源B 的时候,线程 B 同样也是先尝试获取资源A,然后尝试获取资源 B。也就是说,线程 A 和线程 B 总是以相同的顺序申请⾃⼰想要的资源,即破坏了环路等待条件。


三、 互斥锁和⾃旋锁

最底层的两种就是「互斥锁和⾃旋锁」,有很多⾼级的锁都是基于它们实现的


互斥锁加锁失败后,线程会释放 CPU ,给其他线程; ⾃旋锁加锁失败后,线程会忙等待,直到它拿到锁;


对于互斥锁加锁失败⽽阻塞的现象,是由操作系统内核实现的。当加锁失败时,内核会将线程置为「睡眠」状态,等到锁被释放后,内核会在合适的时机唤醒线程,当这个线程成功获取到锁后,于是就可以继续执⾏。


所以,互斥锁加锁失败时,会从⽤户态陷⼊到内核态,让内核帮我们切换线程,虽然简化了使⽤锁的难度,但是存在⼀定的性能开销成本。


那这个开销成本是什么呢?会有两次线程上下⽂切换的成本:


当线程加锁失败时,内核会把线程的状态从「运⾏」状态设置为「睡眠」状态,然后把CPU 切换给其他线程运⾏;接着,当锁被释放时,之前「睡眠」状态的线程会变为「就绪」状态,然后内核会在合适的时间,把 CPU 切换给该线程运⾏。


如果你能确定被锁住的代码执⾏时间很短,就不应该⽤互斥锁,⽽应该选⽤⾃旋锁,否则使⽤互斥锁。


⾃旋锁是通过 CPU 提供的 CAS 函数(Compare And Swap),在「⽤户态」完成加锁和解锁操作,不会主动产⽣线程上下⽂切换,所以相⽐互斥锁来说,会快⼀些,开销也⼩⼀些。


⾃旋锁与互斥锁使⽤层⾯⽐较相似,但实现层⾯上完全不同:当加锁失败时,互斥锁⽤「线程切换」来应对,⾃旋锁则⽤「忙等待」来应对。


目录
相关文章
|
1月前
|
存储 Unix Linux
手写操作系统(4)——计算机是如何启动的?BIOS、GRUB、文件系统......
手写操作系统(4)——计算机是如何启动的?BIOS、GRUB、文件系统......
38 1
|
11天前
|
运维 安全 Linux
计算机架构“寒武纪爆发”,操作系统进化迸发中国浪潮
计算机架构“寒武纪爆发”,操作系统进化迸发中国浪潮
|
1月前
|
安全 算法 程序员
操作系统(9)----死锁
操作系统(9)----死锁
25 1
|
1月前
|
存储 算法 Linux
【计算机操作系统】深入探究CPU,PCB和进程工作原理
【计算机操作系统】深入探究CPU,PCB和进程工作原理
|
1月前
|
监控 Linux 调度
操作系统学习笔记(一)
在Linux中,使用`ps -aux | grep PID`来查看特定进程的状态,或者用`top`指令监控进程和内存。通过`cat 文件名 | grep 关键词`或`grep -i 关键词 文件名`搜索日志文件。`grep`是一个强大的文本搜索工具,支持多种参数,如`-i`忽略大小写,`-c`计数,`-f`从文件读取关键词。要临时更改主机名用`hostname 新主机名`,永久更改则用`hostnamectl set-hostname 新主机名`
|
1月前
|
消息中间件
操作系统学习笔记(二)
进程切换比线程切换更消耗资源,因为进程切换需保存更多上下文,包括地址空间、寄存器、栈和文件描述符等,还要刷新TLB。线程切换仅需切换硬件上下文和内核栈,上下文更小,所以开销低。进程间通信有多种方式,如匿名管道(父子进程间)、命名管道(无亲缘关系进程)、信号、消息队列、共享内存和信号量等。这些通信方法各有特点,适用于不同场景。例如,匿名管道是半双工的,有名管道允许任何进程通过路径通信,信号用于进程间的简单通知,消息队列支持随机查询和按类型读取,共享内存允许多进程共享数据,而信号量则用于同步和控制对共享资源的访问。
|
1月前
|
存储 安全 数据处理
【计算机系统组成原理】操作系统处理器深入介绍
【计算机系统组成原理】操作系统处理器深入介绍
|
1月前
|
存储 缓存 安全
【linux基础(八)】计算机体系结构--冯诺依曼系统&操作系统的再理解
【linux基础(八)】计算机体系结构--冯诺依曼系统&操作系统的再理解
|
20天前
|
存储 Linux 数据处理
探索Linux操作系统的内核与文件系统
本文深入探讨了Linux操作系统的核心组件,包括其独特的内核结构和灵活的文件系统。文章首先概述了Linux内核的主要功能和架构,接着详细分析了文件系统的工作原理以及它如何支持数据存储和检索。通过比较不同的文件系统类型,本文旨在为读者提供一个关于如何根据特定需求选择合适文件系统的参考框架。
|
10天前
|
存储 缓存 安全
Linux基础——冯诺依曼体系结构与操作系统
Linux基础——冯诺依曼体系结构与操作系统
36 1
Linux基础——冯诺依曼体系结构与操作系统