014 Linux_同步

​🌈个人主页:Fan_558
🔥 系列专栏:Linux
🌹关注我💪🏻带你学更多操作系统知识

在这里插入图片描述

文章目录

  • 前言
    • 一、死锁
      • (1)死锁概念
    • 二、同步
      • (1)同步概念
      • (2)条件变量
      • (3)函数接口
      • (4)代码实例
  • 小结

前言

本文将会向你介绍死锁的概念,以及同步的概念和实现

一、死锁

(1)死锁概念

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

举个例子,F1与F2去买奶茶,此时F1和F2手中都有5块钱,奶茶需要十块钱,F1伸手向F2要钱,F2不肯,并说你把钱给我,F1自然也是不愿意的,那么他们手中都有五元钱,又互相申请对方的五元钱,双方都不肯放手

死锁四个必要条件

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

避免死锁

破坏死锁的四个必要条件
加锁顺序一致
避免锁未释放的场景
资源一次性分配

在这里插入图片描述
Lock申请锁失败,线程会阻塞住,不会返回,trylock是申请锁的非阻塞版本

二、同步

(1)同步概念

同步:在保证数据安全的前提下,让线程能够按照某种特定的顺序访问临界资源,从而有效避免饥饿问题,叫做同步(前文我们提到公共独立自习室的例子,若一个人长时间持有钥匙,当他出门并把钥匙重新放回原处的时候,看到一大堆人在等他出来,他不想失去这个自习室,于是他又进去了,他那么轻松再次进去的原因就是他距离钥匙更近些,对钥匙的竞争力更大,线程也是如此)。若是其它线程长时间不能得到共享资源,势必会导致饥饿问题
前一篇文章我们也提到:定一个规矩:出来的人,不能立马重新申请锁,想要继续申请,必须排到队列的最后面,外面来的,必须排队

(2)条件变量

要么继续申请锁要么退出,不管要干什么做后续工作之前,必须把铃铛敲一下
把铃铛和队列称为条件变量(提供一种简单的通知机制:唤醒线程,并提供一个队列
让线程在等待队列中排队)
在这里插入图片描述

(3)函数接口

1、初始化条件变量
静态分配:

pthread_cond_t cond=PTHREAD_COND_INITIALIZER

注意:静态分配的条件变量不需要手动销毁

动态分配:

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

2、利用条件变量等待资源就绪

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

3、资源就绪后,主线程唤醒新线程来访问共享资源

int pthread_cond_broadcast(pthread_cond_t *cond); 
int pthread_cond_signal(pthread_cond_t *cond)

4、销毁

int pthread_cond_destroy(pthread_cond_t *cond)

(4)代码实例

#include <iostream>
#include <unistd.h>
#include <pthread.h>
#include <stdint.h>int cnt = 0;
//初始化锁、条件变量
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
void* Count(void* args)
{//线程分离pthread_detach(pthread_self());uint64_t number = (uint64_t)args;while(true){//加锁pthread_mutex_lock(&mutex);//等待pthread_cond_wait(&cond, &mutex);std::cout << "pthread: " << number << ", cnt: " << cnt++ << std::endl;//解锁pthread_mutex_unlock(&mutex);sleep(3);}
}
int main()
{for(uint64_t i = 0; i < 5; i++){pthread_t tid;//创建线程pthread_create(&tid, NULL, Count, (void*)i);}while(true){sleep(1);//唤醒等待队列头部的线程//std::cout << "It's time to get up: one thread" << std::endl;//pthread_cond_signal(&cond);std::cout << "It's time to get up: all thread" << std::endl;pthread_cond_broadcast(&cond);}return 0;
}

这段代码的逻辑本质是这样

加锁-----------
判断共享资源是否就绪
while(不满足){
>等待资源就绪}
>执行接下来的代码
code...
...
解锁-----------

三个疑问:

一、为什么判断条件要放在加锁解锁(临界资源里)之间 原因: 可是我们怎么知道我们要让一个线程去挂起呢(一旦调用该接口pthread_cond_wait(&cond, &mutex)线程就挂起了? 一定是临界资源不就绪,你怎么知道临界资源是就绪还是不就绪呢?
你判断出来的 怎么判断出来的呢?
那一定是有访问该临界资源,否则怎么知道就绪还是不就绪呢。 那么为了防止多并发问题,那么我们是不是应该将会访问临界资源的判断加锁呢?
必须是的,也就是判断必须在加锁之后

二、为什么pthread_cond_wait也要放在加锁和解锁之间
因为当条件不满足的时候就需要去等待

三、pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t
*restrict mutex)为什么第二个参数携带锁

因为当一个线程进到临界区内时,当资源不就绪,该线程就应该去等待,可是如果该线程不释放这把锁就去等待的话,那么下一个线程该如何进入临界区内呢,锁只有一把,所以pthread_cond_wait第二个参数传入一把锁的原因是为了让线程去等待前释放锁

答疑完了,让我们来看看运行结果如何
每次唤醒一个线程,各个线程按照特定的次序访问这批资源
在这里插入图片描述
唤醒所有线程
在这里插入图片描述

小结

今日的分享就到这里啦,如果本文存在疏漏或错误的地方还请您能够指出!

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

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

相关文章

计算机考研|双非一战135上岸,408经验分享+复盘

计算机专业的同学真的别想的太天真&#xff01; 相比于其他专业&#xff0c;计算机专业的同学其实还是很有优势的 但是现在随着计算机专业的同学越来越多&#xff0c;找工作的困难程度以及学历自然而然被卷起来了 以前的算法岗基本要求在本科以上&#xff0c;现在基本都是非92研…

家电工厂5G智能制造数字孪生可视化平台,推进家电工业数字化转型

家电5G智能制造工厂数字孪生可视化平台&#xff0c;推进家电工业数字化转型。随着科技的飞速发展&#xff0c;家电行业正迎来一场前所未有的数字化转型。在这场制造业数字化转型中&#xff0c;家电5G智能制造工厂数字孪生可视化平台扮演着至关重要的角色。本文将从数字孪生技术…

提交数据加快百度搜索引擎收录

百度站长工具做了更新&#xff0c;百度收录的地址分享如下&#xff0c;新站点提交后&#xff0c;可以加快百度收录。 普通收录_加快网站内容抓取&#xff0c;快速提交数据工具_站长工具_网站支持_百度搜索资源平台普通收录工具可实时向百度推送数据&#xff0c;创建并提交site…

git 安装、创建仓库、常用命令、克隆下载、上传项目、删除分支 -- 一篇文章总结

一、git安装 1、git安装地址&#xff1a;https://git-scm.com/downloads 2、选择操作系统 3、安装自己系统对应的操作位数 4、等待下载完&#xff0c;一路next安装就可以了 5、安装完成后&#xff0c;在任意文件夹点击右键&#xff0c;看到下图说明安装成功 二、创建仓库 1…

云原生(二)、Docker基础

Docker Docker 是一种开源的容器化平台&#xff0c;用于开发、部署和运行应用程序。它允许开发者将应用程序及其所有依赖项打包到一个可移植的容器中&#xff0c;这个容器可以在任何支持 Docker 的环境中运行&#xff0c;无论是开发人员的个人笔记本电脑、测试环境、生产服务器…

ROS Kinetic通信编程:话题、服务、动作编程

文章目录 一、话题编程二、服务编程三、动作编程 接上篇&#xff0c;继续学习ROS通信编程基础 一、话题编程 步骤&#xff1a; 创建发布者 初始化ROS节点向ROS Master注册节点信息&#xff0c;包括发布的话题名和话题中的消息类型按照一定频率循环发布消息 创建订阅者 初始化…

stm32-编码器测速

一、编码器简介 编码电机 旋转编码器 A,B相分别接通道一和二的引脚&#xff0c;VCC&#xff0c;GND接单片机VCC&#xff0c;GND 二、正交编码器工作原理 以前的代码是通过触发外部中断&#xff0c;然后在中断函数里手动进行计次。使用编码器接口的好处就是节约软件资源。对于频…

从0开始回顾MySQL---事务四大特性

事务概述 事务是一个最小的工作单元。在数据库当中&#xff0c;事务表示一件完整的事儿。一个业务的完成可能需要多条DML语句共同配合才能完成&#xff0c;例如转账业务&#xff0c;需要执行两条DML语句&#xff0c;先更新张三账户的余额&#xff0c;再更新李四账户的余额&…

实现elasticsearch和数据库的数据同步

1. 数据同步 elasticsearch中的酒店数据来自于mysql数据库&#xff0c;因此mysql数据发生改变时&#xff0c;elasticsearch也必须跟着改变&#xff0c;这个就是elasticsearch与mysql之间的数据同步。 1.1. 思路分析 常见的数据同步方案有三种&#xff1a; 同步调用 异步通知…

面试题手撕篇

参考博客 开始之前&#xff0c;理解递归 手写 浅拷贝 function shallow(target){if(target instanceof Array){return [...resObj]}else{return Object.assign({},target);} }手写深拷贝 const _sampleDeepClone target > {// 补全代码return JSON.parse(JSON.stringify…

EtherCAT开源主站 IGH 介绍及主站伺服控制过程

目录 前言 IGH EtherCAT主站介绍 主要特点和功能 使用场景 SOEM 主站介绍 SOEM 的特点和功能 SOEM 的使用场景 IGH 主站 和 SOEM对比 1. 功能和复杂性 2. 资源消耗和移植性 3. 使用场景 EtherCAT 通信原理 EtherCAT主站控制伺服过程 位置规划模式 原点复归模式…

Ansible非标记语言YAML与任务剧本Playbook

前言 上篇介绍了 Ansible 单模块&#xff08;AD-Hoc&#xff09;的相关内容Ansible自动化运维Inventory与Ad-Hoc-CSDN博客&#xff0c;Ad-Hoc 命令是一次性的、即时执行的命令&#xff0c;用于在远程主机上执行特定任务&#xff0c;这些命令通常用于快速执行简单的任务。当需要…

MS08-067 漏洞利用与安全加固

文章目录 环境说明1 MS08_067 简介2 MS08_067 复现过程3 MS08_067 安全加固 环境说明 渗透机操作系统&#xff1a;2024.1漏洞复现操作系统: Windows XP Professional with Service Pack 2- VL (English)安全加固复现操作系统&#xff1a;Windows XP Professional with Service …

C语言案例2,请编程序将“China“译成密码,密码规律是:用原来的字母后面第4个字母代替原来的字母,变为Glmre,持续更新~

一.题目 /* 请编程序将“China”译成密码,密码规律是:用原来的字母后面第4个字母代替原来的字母。 例如,字母“A”后面第4个字母是“E”&#xff0c;用“E”代替“A”。因此,“China”应译为“Glmre”。 请编一程序,用赋初值的方法使cl,c2&#xff0c;c3,c4,c5 这5个变量的值分…

YoloV5改进策略:下采样改进|HWD改进下采样

摘要 本文使用HWD改进下采样&#xff0c;在YoloV5的测试中实现涨点。 论文解读 在卷积神经网络&#xff08;CNNs&#xff09;中&#xff0c;极大池化或跨行卷积等下采样操作被广泛用于聚合局部特征、扩大感受野和最小化计算开销。然而&#xff0c;对于语义分割任务&#xff…

HTML_CSS练习:HTML注释

一、代码示例 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>HTML注释</title> </head> <body><marquee loop"1">马龙强<!--下面的输入框是可以滚动的&#x…

【Python】清理conda缓存的常用命令

最近发现磁盘空间不足&#xff0c;很大一部分都被anaconda占据了&#xff0c;下面是一些清除conda缓存的命令 清理所有环境的Anaconda包缓存 删除所有未使用的包以及缓存的索引和临时文件 conda clean --all清理某一特定环境的Anaconda包缓存 conda clean --all -n 环境名清…

【ansible】ansible的介绍和安装

前言运维自动化 云计算核心职能 搭建平台架构 日常运营保障 性能效率优化 相关工具 代码管理&#xff08;SCM&#xff09;&#xff1a;GitHub、GitLab、BitBucket、SubVersion 构建工具&#xff1a;maven、Ant、Gradle 自动部署&#xff1a;Capistrano、CodeDeploy 持续…

字符串函数(C语言详解)

1.字符串简介 字符串是一串连续的且以\0结尾的字符 char arr[]"zhangsan";//将字符串存到数组里面 char*a"lisi";//常量字符串 char arr1[]{z,h,a,n,g};//字符数组 注意&#xff1a; 1.以第一种形式初始化字符串时&#xff0c;计算机会自动在字符串末尾加…

GraspNet-baseline复现----Linux-Ubuntu

1.基本环境 Ubuntu 20.04Cuda 11.0 、cuDNN 80.0Python 3.7.16PyTorch 1.7.0 2.环境配置 PyTorch的版本对Cuda和Python的版本都有依赖&#xff0c;所以基本步骤是 确定需要安装的PyTorch版本 —> 通过 网站 确定对应的cuda版本和python版本 —> 创建虚拟环境配置环境。…