39 死锁

目录

1.死锁
2.线程同步
3.条件变量
4.案例

死锁

概念

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

四个必要条件

互斥条件:一个资源每次只能被一个执行流使用
请求与保持:一个执行流因请求资源而阻塞时,对已获得资源保持不放
不剥夺条件:一个执行流已获得的资源,在未使用完之前,不能强行剥夺
循环等待条件:若干执行流之间形成一种头尾相接的循环等待资源的关系,a的执行需要申请b的不释放资源,b的执行需要a的不释放资源

避免死锁

破坏死锁的四个必要条件。第一个互斥条件需要重写逻辑结构,比较困难。二和三都有对应的函数,请求与保持在加锁的时候是阻塞等待,有一个函数加锁是非阻塞等待的
加锁顺序一致
避免锁未释放的场景
资源一次性分配。资源不要分好几次给,一次性给完。就等减少死锁的可能

算法

避免死锁算法
银行家算法

线程同步

概念

上一节的买票程序,会出现只有一个线程经常抢到票。根本原因是线程对锁的竞争能力不同,拥有锁的线程在使用完后又会立即拿到锁,重新买票,导致其他线程都阻塞在加锁函数里。
这种情况的解决办法就是让阻塞的线程都排好队,新到的线程排到队列的最后面,按顺序获得锁。拥有锁的线程在使用完后不要立马去申请,而是自动排到队列最后面

同步:保证数据安全的情况下,让线程访问资源具有一定的顺序性

保证同步的一种方法就是条件变量

条件变量

概念

当一个线程互斥的访问某个变量时,它可能发现在其他线程改变状态前,神恶魔也做不了
例如一个线程访问队列时,发现队列为空,只能等待,直到其他线程将一个节点添加到队列中,这种情况就需要用到条件变量
在这里插入图片描述

当线程申请锁失败就到这个队列里排着,这样队列里就有一堆按顺序排的线程,新的线程也按这个过程。当拥有锁的线程使用完归还锁后,先敲一下铃铛,然后排到队列最后。铃铛被敲后唤醒队列中的线程申请使用锁。这个铃铛这部分就是条件变量。根据上面情形,条件变量必须依赖于锁的使用。os对这两个锁和条件变量结构也需要维护

为什么需要互斥量

条件等待是线程间同步的一种手段,如果只有一个线程,条件不满足,一直等下去都不会满足,所以必须要有一个线程通过某些操作,改变共享变量,使原先不满足的条件变得满足,并且友好的通知等待在条件变量上的线程
条件不会无缘无故的突然满足,必然牵扯到共享数据的变化。所以一定要用互斥锁来保护,没有互斥锁就无法安全的获取和修改共享数据

在这里插入图片描述
由于解锁和等待不是原子的,调用解锁之后,wait之前,如果已经有其他线程获取到互斥量,掘弃条件满足,发送了信号,那么wait将错过这个信号,可能导致线程永远阻塞在wait,所以解锁和等待必须是原子操作

wait进入函数后,回去查看条件变量等于0吗,等于就把互斥量变为1,直到wait返回,把条件变量改为1,把互斥量恢复为原样

条件变量使用规范

等待条件代码

pthread_mutex_lock(&mutex);
while (条件为假)
pthread_cond_wait(cond, mutex);
修改条件
pthread_mutex_unlock(&mutex);

给条件发送信号代码

pthread_mutex_lock(&mutex);
设置条件为真
pthread_cond_signal(cond);
pthread_mutex_unlock(&mutex);

同步概念和竞态条件

同步:在保证数据安全的前提下,让线程能够按照某种特定的顺序访问临界资源,从而有效避免饥饿问题,叫同步
竞态条件:因为时序问题,导致程序异常,称之为竞态条件

条件变量初始化

int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t *restrict attr);
参数:
cond:要初始化的条件变量
attr:NULL

在这里插入图片描述

销毁

int pthread_cond_destroy(pthread_cond_t *cond)

等待条件满足

int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex);
参数:
cond:要在这个条件变量上等待
mutex:互斥量,后面详细解释

唤醒

int pthread_cond_broadcast(pthread_cond_t *cond); //全部
int pthread_cond_signal(pthread_cond_t *cond); //一个

条件变量和锁的使用类似,都可以局部和全局定义,全局则不需要初始化和销毁

案例

五个线程对cnt变量加加,用锁和条件变量保证线程安全和顺序性

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <iostream>int cnt = 0;
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
void *count(void *num)
{uint64_t i = (uint64_t)num;while (true){pthread_mutex_lock(&lock);pthread_cond_wait(&cond, &lock);printf("线程 %d cnt:%d\n", i, cnt++);pthread_mutex_unlock(&lock);}
}int main()
{//64位整形,强转指针for (uint64_t i = 0; i < 5; i++){pthread_t tid;//不能取i的地址传入,线程里访问的和这里的i会是同一个变量,//一个修改,另一个读取错误pthread_create(&tid, nullptr, count, (void*)i);//usleep(13);}sleep(3);while (true){//pthread_cond_signal(&cond);pthread_cond_broadcast(&cond);printf("唤醒\n");sleep(1);}return 0;
}

在这里插入图片描述

我们怎么知道一个线程需要休眠?一定是临界资源不就绪时,临界资源也是有状态的,而临界资源有没有就绪时判断出来的。判断也是访问临界资源的过程,所以注定了休眠时在加锁和解锁之间。条件变量的等待函数会自动释放锁,所以必须在申请和释放锁中间

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

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

相关文章

LeetCode题练习与总结:柱状图中最大的矩形--84

一、题目描述 给定 n 个非负整数&#xff0c;用来表示柱状图中各个柱子的高度。每个柱子彼此相邻&#xff0c;且宽度为 1 。 求在该柱状图中&#xff0c;能够勾勒出来的矩形的最大面积。 示例 1: 输入&#xff1a;heights [2,1,5,6,2,3] 输出&#xff1a;10 解释&#xff1a…

硬盘选购指南

转载请注明出处&#xff01; author karrysmile date 2024年5月3日19:10:52 结论 先给用途分类和价格表 前置知识 没有不好的品牌&#xff0c;只有不好的系列。不用认准哪个品牌就不好&#xff0c;认准口碑好&#xff0c;稳定性好的系列买。&#xff08;杂牌别买&#xff0…

82、动态规划-杨辉三角

思路&#xff1a; 本题其实很容易看出来&#xff0c;首尾都是1&#xff0c;然后第2个元素就是上一行的第一个元素和第二个元素之和。依次类推。可以得出结论&#xff1a;dp[i][j]dp[i-1][j-1]dp[i-1][j],当然要去掉首尾元素。代码如下&#xff1a; public static List<List&…

AtCoder Beginner Contest 351 C题

C - Merge the balls Time Limit: 2 sec / Memory Limit: 1024 MB Score 250 points Problem Statement You have an empty sequence and &#x1d441;N balls. The size of the &#x1d456;i-th ball (1≤&#x1d456;≤&#x1d441;) is ​2^A[i] You will perform…

内网安全-代理Socks协议路由不出网后渗透通讯CS-MSF控制上线简单总结

我这里只记录原理&#xff0c;具体操作看文章后半段或者这篇文章内网渗透—代理Socks协议、路由不出网、后渗透通讯、CS-MSF控制上线_内网渗透 代理-CSDN博客 注意这里是解决后渗透通讯问题&#xff0c;之后怎么提权&#xff0c;控制后面再说 背景 只有win7有网&#xff0c;其…

Day01-zabbix监控详解

Day01-zabbix监控详解 一、什么是监控&#xff0c;为什么需要监控1.1 监控概述1.2 监控课程大纲 二、Linux的那些独孤九剑级别的命令五、监控的现代时六、Zabbix监控架构6.1 生命周期6.2 Zabbix监控架构 七、Zabbix 6.x Centos7 生产快速实践指南7.1 主机规划1&#xff09; 推荐…

23- ESP32 红外遥控 (RMT)

ESP32 IDF库中的RMT驱动 RMT&#xff08;Remote Control Module&#xff09;驱动是ESP-IDF库中的一个重要组成部分&#xff0c;它主要用于处理远程控制编码和解码。 红外遥控器介绍 一、红外遥控技术介绍 红外遥控是一种无线、非接触控制技术&#xff0c;具有抗干扰能力强&…

ASP.NET网络在线考试系统

摘 要 随着计算机技术的发展和互联网时代的到来&#xff0c;人们已经进入了信息时代&#xff0c;也有人称为数字化时代。数在数字化的网络环境下&#xff0c;学生希望得到个性化的满足&#xff0c;根据自己的情况进行学习&#xff0c;同时也希望能够得到科学的评价&#xff0c…

【深度学习】第一门课 神经网络和深度学习 Week 3 浅层神经网络

&#x1f680;Write In Front&#x1f680; &#x1f4dd;个人主页&#xff1a;令夏二十三 &#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐️ 留言&#x1f4dd; &#x1f4e3;系列专栏&#xff1a;深度学习 &#x1f4ac;总结&#xff1a;希望你看完之后&#xff0c;能对…

Kelpa-小型服务器开发框架分享

分享我的服务器开发框架--Kelpa&#xff1a; 这是一个由现代C编写的小型、学习性质的服务器框架&#xff0c;包含压缩&#xff0c;序列化&#xff0c;IO调度&#xff0c;Socket封装&#xff0c;文件配置&#xff0c;日志库等多个完整自研模块&#xff1a; 项目目前仍处于开发阶…

QT:输入类控件的使用

LineEdit 录入个人信息 #include "widget.h" #include "ui_widget.h" #include <QDebug> #include <QString>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);// 初始化输入框ui->lineEdit…

文本嵌入的隐私风险:从嵌入向量重建原始文本的探索

随着大型语言模型&#xff08;LLMs&#xff09;的广泛应用&#xff0c;文本嵌入技术在语义相似性编码、搜索、聚类和分类等方面发挥着重要作用。然而&#xff0c;文本嵌入所蕴含的隐私风险尚未得到充分探讨。研究提出了一种控制生成的方法&#xff0c;通过迭代修正和重新嵌入文…

嵌入式硬件中PCB走线与过孔的电流承载能力分析

简介 使用FR4敷铜板PCBA上各个器件之间的电气连接是通过其各层敷着的铜箔走线和过孔来实现的。 由于不同产品、不同模块电流大小不同,为实现各个功能,设计人员需要知道所设计的走线和过孔能否承载相应的电流,以实现产品的功能,防止过流时产品烧毁。 文中介绍设计和测试FR4敷…

【探索】文字游侠AI新时代,每天5分钟自动化创作图文月入1万+,十分适合新手小白,附上渠道和教程(全面)

在这个信息爆炸的时代&#xff0c;内容创作者面临着空前的竞争。为了在今日头条这样的平台上脱颖而出并获取稳定收入&#xff0c;他们需要找到更高效、更创新的方法。而今&#xff0c;一款全新的AI工具正引领着一场革命&#xff0c;彻底改变了内容创作的生态。 自从GPT问世以来…

Quad SPI的DLP优化原理

1 前言 1.1 Quad SPI Flash QSPI的I/O接口如图1所示&#xff0c;其中&#xff1a; ① CS&#xff1a;片选信号&#xff0c;低电平有效&#xff08;FLASH被选中&#xff09;&#xff1b; ② CK&#xff1a;时钟信号&#xff0c;由主设备产生&#xff1b; ③ SI/SO&#xff1a; …

开源的 RAG 和 workflow 技术对比调研

一、先来了解一下开源的技术有哪些&#xff0c;怎么样 我自己就是做RAG工作的&#xff0c;但是还是想关注一下开源的技术做到了什么程度。 所以调研了很长时间&#xff0c;也体验了一下。这里写一篇文章来分享一下结果。 我用五一的假期时间&#xff0c;来做调研&#xff0c;看…

扩展学习|本体研究进展

文献来源&#xff1a; 王向前,张宝隆,李慧宗.本体研究综述[J].情报杂志,2016,35(06):163-170. 一、本体的定义 本体概念被引入人工智能、知识工程等领域后被赋予了新的含义。然而不同的专家学者对本体的理解不同,所给出的定义也有所差异。 人工智能领域的学者Neches(1991)等人对…

常用AI工具分享 + IDEA内使用通义灵码

引言 随着人工智能技术的飞速发展&#xff0c;AI工具已经渗透到我们日常生活和工作的各个领域&#xff0c;带来了前所未有的便利。现在我将分享一下常用的AI工具&#xff0c;以及介绍如何在IDEA中使用通义灵码。 常用AI工具 1. 通义灵码 (TONGYI Lingma) - 由阿里云开发的智能…

时间复杂度空间复杂度 力扣:转轮数组,消失的数字

1. 算法效率 如何衡量一个算法的好坏&#xff1f;一般是从时间和空间的维度来讨论复杂度&#xff0c;但是现在由于计算机行业发展迅速&#xff0c;所以现在并不怎么在乎空间复杂度了下面例子中&#xff0c;斐波那契看上去很简洁&#xff0c;但是复杂度未必如此 long long Fib…

Java -- (part20)

一.Map集合 1.概述 双列集合的顶级接口 2.实现类 HashMap 特点: a.key唯一,value可重复->如果key重复了,会发生value覆盖 b.无序 c.无索引 d.线程不安全 e.可以存null键null值 数据结构: 哈希表 方法: LinkedHashMap 特点: a.key唯一,value可重复->如果ke…