【操作系统】死锁

1. 定义

死锁是指两个或多个进程(或线程)在执行过程中,因争夺资源而造成的一种僵局,每个进程都无限期地等待其他进程释放它们所持有的资源。在这种情况下,没有任何进程能够继续执行,除非有外部干预。

2. 死锁的必要条件

根据Dijkstra的理论,死锁的发生必须同时满足以下四个必要条件:

  1. 互斥条件(Mutual Exclusion)

    • 资源不能被共享,一次只能被一个进程使用。例如,打印机、磁带机等资源在使用时不能被多个进程同时占用。

  2. 请求与保持条件(Hold and Wait)

    • 一个进程已经持有一个资源,但又请求新的资源。如果新资源被其他进程占用,请求进程将被阻塞,但它仍然保持对已有资源的占用。

  3. 不可剥夺条件(No Preemption)

    • 资源不能被强制剥夺,只能由占用它的进程主动释放。例如,内存资源不能被强制从一个进程转移到另一个进程。

  4. 循环等待条件(Circular Wait)

    • 存在一个进程序列 P1​,P2​,…,Pn​,使得 P1​ 等待 P2​ 持有的资源,P2​ 等待 P3​ 持有的资源,……,Pn​ 等待 P1​ 持有的资源,形成一个等待环路。

3. 死锁的示例
哲学家进餐问题

哲学家进餐问题是死锁的经典示例。五位哲学家围坐在一张圆桌旁,每位哲学家面前有一支叉子,左右各一支。哲学家需要同时拿起左右两支叉子才能进餐。如果每位哲学家都先拿起左边的叉子,然后等待右边的叉子,最终会导致所有哲学家都饿死,因为每个人都持有一支叉子并等待另一支叉子。

银行家算法

银行家算法是一种预防死锁的算法,通过资源分配图来检测系统是否处于安全状态。如果系统处于安全状态,银行家算法会分配资源;否则,它会等待,直到系统进入安全状态。银行家算法通过确保系统不会进入不安全状态来预防死锁。

4. 死锁的处理策略
  1. 预防死锁(Deadlock Prevention)

    • 通过破坏死锁的必要条件之一来预防死锁的发生。例如:

      • 资源分级:对资源进行编号,哲学家总是先拿起编号较小的叉子,再拿起编号较大的叉子,从而破坏循环等待条件。

      • 限制资源分配:限制同时请求资源的数量,确保系统不会进入死锁状态。

  2. 避免死锁(Deadlock Avoidance)

    • 动态地检查资源分配是否会导致死锁。例如:

      • 银行家算法:通过资源分配图来检测系统是否处于安全状态,只在安全状态下分配资源。

  3. 检测死锁(Deadlock Detection)

    • 定期检查系统是否处于死锁状态。如果检测到死锁,采取措施解决。例如:

      • 资源分配图:通过资源分配图检测循环等待条件。

      • 超时机制:如果某个进程等待资源的时间超过某个阈值,认为系统可能进入死锁状态。

  4. 恢复死锁(Deadlock Recovery)

    • 当检测到死锁时,采取措施恢复系统。例如:

      • 资源剥夺:强制剥夺某些进程持有的资源,使其能够继续执行。

      • 进程终止:终止某些进程,释放其持有的资源。

5. 死锁的示例代码

以下是一个简单的C语言示例,展示如何通过资源分级来预防死锁。

 

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>#define NUM_PHILOSOPHERS 5sem_t forks[NUM_PHILOSOPHERS];void* philosopher(void* arg) {int id = *(int*)arg;int left_fork = id;int right_fork = (id + 1) % NUM_PHILOSOPHERS;while (1) {// 思考printf("Philosopher %d is thinking\n", id);sleep(1);// 饿了,尝试拿起叉子printf("Philosopher %d is hungry\n", id);// 确保先拿起编号较小的叉子if (left_fork < right_fork) {sem_wait(&forks[left_fork]);printf("Philosopher %d picked up left fork %d\n", id, left_fork);sem_wait(&forks[right_fork]);printf("Philosopher %d picked up right fork %d\n", id, right_fork);} else {sem_wait(&forks[right_fork]);printf("Philosopher %d picked up right fork %d\n", id, right_fork);sem_wait(&forks[left_fork]);printf("Philosopher %d picked up left fork %d\n", id, left_fork);}// 吃饭printf("Philosopher %d is eating\n", id);sleep(1);// 放下叉子sem_post(&forks[right_fork]);printf("Philosopher %d put down right fork %d\n", id, right_fork);sem_post(&forks[left_fork]);printf("Philosopher %d put down left fork %d\n", id, left_fork);}
}int main() {pthread_t philosophers[NUM_PHILOSOPHERS];int ids[NUM_PHILOSOPHERS];// 初始化信号量for (int i = 0; i < NUM_PHILOSOPHERS; i++) {sem_init(&forks[i], 0, 1);}// 创建哲学家线程for (int i = 0; i < NUM_PHILOSOPHERS; i++) {ids[i] = i;pthread_create(&philosophers[i], NULL, philosopher, &ids[i]);}// 等待线程结束for (int i = 0; i < NUM_PHILOSOPHERS; i++) {pthread_join(philosophers[i], NULL);}// 清理信号量for (int i = 0; i < NUM_PHILOSOPHERS; i++) {sem_destroy(&forks[i]);}return 0;
}

代码说明

  • 资源分级:哲学家总是先拿起编号较小的叉子,再拿起编号较大的叉子,从而破坏循环等待条件。

  • 信号量:使用信号量来控制叉子的获取和释放,确保资源的互斥访问。

总结

死锁是并发系统中一个常见的问题,通过理解死锁的必要条件和采取适当的处理策略,可以有效地预防和解决死锁问题。资源分级是一种简单而有效的预防死锁的方法,通过打破循环等待条件,确保系统不会进入死锁状态。

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

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

相关文章

C++入门☞关于类的一些特殊知识点

涉及的关于类中的默认成员函数的知识点可以看我的这篇博客哦~ C入门必须知道的知识☞类的默认成员函数&#xff0c;一文讲透运用 目录 初始化列表 类型转换 static成员 友元 内部类 匿名对象 对象拷贝时的一些编译器的优化 初始化列表 我们知道类中的构造函数的任务是完…

只用Prettier进行格式化项目

1.下载Prettier插件&#xff0c;禁用ESlint 2.在项目根目录新建.prettierrc文件 {"singleQuote": true,"jsxSingleQuote": true,"printWidth": 100,"trailingComma": "none","tabWidth": 2,"semi": f…

XXL-TOOL v1.4.0 发布 | Java工具类库

Release Notes 1、【新增】JsonRpc模块&#xff1a;一个轻量级、跨语言远程过程调用实现&#xff0c;基于json、http实现&#xff08;从XXL-JOB底层通讯组件提炼抽象&#xff09;。2、【新增】Concurrent模块&#xff1a;一系列并发编程工具&#xff0c;具备良好的线程安全、高…

基于LVGL的登录界面设计

目录 一、演示 二、前言 三、部件知识 3.1 图片按钮部件 3.1.1 图片按钮部件的组成 3.1.2 图片的来源 3.1.3 添加/清除的状态 3.1.4 图片按钮部件 API 函数 3.2 键盘部件(lv_keyboard) 3.2.1 键盘部件的组成 3.2.2 键盘部件的相关知识 3.2.2.1 键盘部件模式 3.…

S3 跨账户复制:增强云中的灾难恢复计划

您准备好提升您的云和 DevOps 技能了吗&#xff1f; &#x1f425;《云原生devops》专门为您打造&#xff0c;我们精心打造的 30 篇文章库&#xff0c;这些文章涵盖了 Azure、AWS 和 DevOps 方法论的众多重要主题。无论您是希望精进专业知识的资深专业人士&#xff0c;还是渴望…

线程与进程深度解析:从fork行为到生产者-消费者模型

线程与进程深度解析&#xff1a;从fork行为到生产者-消费者模型 一、多线程环境下的fork行为与线程安全 1. 多线程程序中fork的特殊性 核心问题&#xff1a;fork后子进程的线程模型 当多线程程序中的某个线程调用fork时&#xff1a; 子进程仅包含调用fork的线程&#xff1…

Circular Plot系列(五): circle plot展示单细胞互作

这是我们circle系列的最后一节&#xff0c;我想常见的弦图是绕不开的&#xff0c;所以最后从前面介绍的circle plot思路&#xff0c;做一遍弦图。其实前面的内容如果消化了&#xff0c;plot互作弦图也就不成什么问题了。 效果如下&#xff1a; #cellchat提取互作结果&#xff…

(11)Vue-Router路由的详细使用

本系列教程目录&#xff1a;Vue3Element Plus全套学习笔记-目录大纲 文章目录 第2章 路由 Vue-Router2.1 Vue路由快速入门2.1.1 创建项目2.1.2 路由运行流程 2.2 传递参数-useRoute2.2.1 路径参数-params1&#xff09;普通传参2&#xff09;传递多个参数3&#xff09;对象方式传…

react + antd 实现后台管理系统

文章目录 完整路由搭建Layout 和 Aside组件引入 AntdAside组件实现 项目效果图 项目完整代码地址 https://gitee.com/lyh1999/react-back-management 项目完整代码地址 react依赖安装 最好采用yarn 安装 react-router 安装依赖 配置路由 history模式 / // src/router/…

基于AWS Marketplace的快速解决方案:从选型到部署实战

1. 引言&#xff1a;为什么选择AWS Marketplace&#xff1f; 在数字化转型的背景下&#xff0c;企业需要快速获取成熟的软件工具和服务以降低开发成本。AWS Marketplace 作为亚马逊云科技的官方应用商店&#xff0c;提供超过万款预配置的第三方和AWS原生解决方案&#xff0c;涵…

2021年第十二届蓝桥杯省赛B组C++题解

2021年第十二届蓝桥杯省赛B组C题解 关键词&#xff1a;蓝桥杯、省赛、题解、C、算法 一、个人见解 第十二届蓝桥杯省赛B组共有10道题目&#xff0c;包含5道填空题&#xff08;T1-T5&#xff09;和5道编程题&#xff08;T6-T10&#xff09;&#xff0c;总分150分。比赛时长4小…

日语学习-日语知识点小记-进阶-JLPT-N1阶段(1):语法单词

日语学习-日语知识点小记-进阶-JLPT-N1阶段&#xff08;1&#xff09;&#xff1a;语法单词 1、前言&#xff08;1&#xff09;情况说明&#xff08;2&#xff09;工程师的信仰&#xff08;3&#xff09;高级语法N1语法和难点一、N1语法学习内容&#xff08;高级语法&#xff…

Python|Pyppeteer实现自动登录小红书(32)

前言 本文是该专栏的第32篇,结合优质项目案例持续分享Pyppeteer的干货知识,记得关注。 本文中,笔者以小红书为例,基于Pyppeteer实现自动登录“小红书”。 需要注意的是,对Pyppeteer不太熟悉的同学,可往前翻阅本专栏前面介绍的Pyppeteer知识点,本专栏将带你了解并熟练使…

【翻译、转载】【转载】LLM 的函数调用与 MCP

来源&#xff1a; https://www.dailydoseofds.com/p/function-calling-mcp-for-llms/ 【代码以图像显示的是原文内容&#xff0c;以代码形式显示的是大模型给出的参考】 LLM 的函数调用与 MCP 在 MCP 变得像现在这样主流&#xff08;或流行&#xff09;之前&#xff0c;大多…

【QT】QT中http协议和json数据的解析-http获取天气预报

QT中http协议和json数据的解析 1.http协议的原理2.QT中http协议的通信流程2.1 方法步骤 3.使用http协议&#xff08;通过http下载图片和获取天气预报信息&#xff09;3.1 http下载网络上的图片(下载小文件)3.1.1 示例代码3.1.2 现象 3.2 获取网络上天气预报3.2.1 免费的天气预报…

hot100:链表倒数k个节点- 力扣(LeetCode)

题目&#xff1a; 实现一种算法&#xff0c;找出单向链表中倒数第 k 个节点。返回该链表中倒数第k个节点。 示例一&#xff1a; 输入&#xff1a;{1,2,3,4,5},2 返回值&#xff1a;{4,5} 说明&#xff1a;返回倒数第2个节点4&#xff0c;系统会打印后面所有的节点来比较。 …

Spring AI 实战:第十一章、Spring AI Agent之知行合一

引言:智能体的知行辩证法 “知为行之始,行为知之成”,王阳明的哲学智慧在AI时代焕发光彩。智能体(LLM Agent)的进化之路,正是"认知-决策-执行"这一闭环的完美诠释: 知明理:融合大语言模型的推理能力与知识图谱的结构化认知行致用:基于ReAct模式的动态工具调…

365打卡第R6周: LSTM实现糖尿病探索与预测

&#x1f368; 本文为&#x1f517;365天深度学习训练营中的学习记录博客 &#x1f356; 原作者&#xff1a;K同学啊 &#x1f3e1; 我的环境&#xff1a; 语言环境&#xff1a;Python3.10 编译器&#xff1a;Jupyter Lab 深度学习环境&#xff1a;torch2.5.1 torchvision0…

W-TinyLFU缓存驱逐算法解析

文章目录 1. 背景与概述1.1 什么是缓存驱逐算法1.2 W-TinyLFU 的定义与价值 2. 核心思想与设计理念2.1 时间局部性与频率局部性的结合2.2 高效的频率统计2.3 窗口机制的引入 3. 架构设计与组件3.1 整体架构3.2 窗口缓存&#xff08;Window Cache&#xff09;3.3 主缓存&#xf…

[特殊字符] 人工智能大模型之开源大语言模型汇总(国内外开源项目模型汇总) [特殊字符]

Large Language Model (LLM) 即大规模语言模型&#xff0c;是一种基于深度学习的自然语言处理模型&#xff0c;它能够学习到自然语言的语法和语义&#xff0c;从而可以生成人类可读的文本。 所谓 "语言模型"&#xff0c;就是只用来处理语言文字&#xff08;或者符号…