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第二个参数传入一把锁的原因是为了让线程去等待前释放锁

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

小结

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python入门(小白友好)

知识图谱 搭建环境 安装Python:Download Python | Python.org 安装PyCharm:Download PyCharm: The Python IDE for data science and web development by JetBrains 注意:专业版本是收费的,新手小白使用社区版(community)即可 创建第一个项目: 一些PyCharm的设置(也适用…

40年创新蝶变,IBM与中国共创新质生产力

2024年是“新质生产力”进入政府工作报告第一年&#xff0c;也是百年追求科技创新的IBM在华40周年&#xff0c;同时IBM全球正全力打造下一代企业生产力平台——突破性的企业混合云与AI。2023年&#xff0c;IBM推出基于开源混合云平台Red Hat Openshift的下一代企业级数据和AI平…

显隐特征融合的指静脉识别网络

文章目录 显隐特征融合的指静脉识别网络总结摘要介绍显隐式特征融合网络(EIFNet)掩膜生成模块(MGM)掩膜特征提取模块(MFEM)内容特征提取模块(CFEM)特征融合模块(FFM) THUFVS实验和结果数据集实现细节评估掩膜生成模型消融实验FFM模块门控层Batch Size损失函数超参数选择 论文 …

Python学习从0到1 day17 Python异常、模块、包

不走心的努力&#xff0c;都是在敷衍自己 ——24.3.19 万字长文&#xff0c;讲解异常、模块、包&#xff0c;看这一篇就足够啦 什么是异常? 当检测到一个错误时&#xff0c;python解释器就无法继续执行了&#xff0c;反而出现了一些错误的提示&#xff0c;这就是所谓的异常&am…

解决重装系统之后,开始菜单找不到Anaconda3相关图标

一、anaconda3安装后在开始菜单找不到&#xff0c;如下图所示 二、进入Anaconda3安装的位置 在安装位置按住shift键鼠标右键&#xff0c;打开poworshell&#xff0c;输入 start cmd最后的结果如图。

联发科MT8797迅鲲1300T规格参数_MTK5G安卓核心板方案定制

联发科MT8797&#xff08;迅鲲1300T&#xff09;平台采用Arm Cortex-A78和Cortex-A55组成的八核架构CPU&#xff0c;以及Arm Mali-G77MC9九核GPU&#xff0c;集成了AI处理器MediaTek APU&#xff0c;支持5G Sub-6GHz全频段和5G双载波聚合,支持1.08亿像素拍照和多镜头组合,以及1…

docker入门(五)—— 小练习,docker安装nginx、elasticsearch

练习 docker 安装 nginx # 搜素镜像 [rootiZbp15293q8kgzhur7n6kvZ home]# docker search nginx NAME DESCRIPTION STARS OFFICIAL nginx …

模拟面试

1.TCP通信中的三次握手和四次挥手过程 三次握手 1.客户端像向服务器端发送连接请求 2.服务器应答连接请求 3.客户端与服务器简历连接 四次挥手&#xff1a; 客户端或服务器端发起断开请求,这里假设客户端发送断开请求 1.客户端向服务器发送断开请求 2.服务器应答断开请求 3.服…

c++类和对象(中)类的6个默认成员函数及const成员函数

&#x1fa90;&#x1fa90;&#x1fa90;欢迎来到程序员餐厅&#x1f4ab;&#x1f4ab;&#x1f4ab; 今日主菜&#xff1a;类和对象 主厨&#xff1a;邪王真眼 所属专栏&#xff1a;c专栏 主厨的主页&#xff1a;Chef‘s blog 前言&#xff1a; 咱们之前也是…

OCP NVME SSD规范解读-13.Self-test自检要求

4.10节Device Self-test Requirements详细描述了数据中心NVMe SSD自检的要求&#xff0c;这一部分规范了设备自身进行各种健康检查和故障检测的过程。自检对于确保SSD的正常运行和提前预防潜在故障至关重要。 在进行设备自检时&#xff0c;设备应当确保不对用户数据造成破坏&am…

Unity类银河恶魔城学习记录11-2 p104 Inventoty源代码

此章节相对较难理解&#xff0c;有时间单独出一章讲一下 Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释&#xff0c;可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili InventoryItem.cs…

三维指静脉生物识别成像设备设计和多视图验证研究

文章目录 三维指静脉生物识别成像设备设计和多视图验证研究总结摘要介绍多视角指静脉识别模型结构内容特征编码Transformer(CFET)主导特征选择模块(DFSM) 实验和结果数据集实施细节视角研究池化层的作用消融实验和SOTA方法比较 论文: Study of 3D Finger Vein Biometrics on I…

openfeign使用fallback指定降级方法无法执行问题

直接点上代码&#xff1a; package com.fuXiApi.api;import com.common.util.MyResult; import com.fuXiApi.api.fallback.UserClientFallback; import com.fuXiApi.dto.UserDTO; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bi…

【Python】使用selenium对Poe批量模拟注册脚本

配置好接码api即可实现自动化注册登录试用一体。 运行后会注册账号并绑定邮箱与手机号进行登录试用。 测试结果30秒一个号 import re import time import requests from bs4 import BeautifulSoup from selenium import webdriver from selenium.webdriver.chrome.options imp…

#Ubuntu(修改root信息)

&#xff08;一&#xff09;发行版&#xff1a;Ubuntu16.04.7 &#xff08;二&#xff09;记录&#xff1a; &#xff08;1&#xff09;命令行终端&#xff1a; a.右键&#xff0c;open terminal b.快捷键 ctrlaltt &#xff08;2&#xff09;进行root修改 sudo passwd &a…

3月19日做题

[NPUCTF2020]验证&#x1f40e; if (first && second && first.length second.length && first!second && md5(firstkeys[0]) md5(secondkeys[0]))用数组绕过first1&second[1] 这里正则规律过滤位(Math.) (?:Math(?:\.\w)?) : 匹配 …

PX4|基于FAST-LIO mid360的无人机室内自主定位及定点悬停

目录 前言环境配置运行fast-lio修改px4位置信息融合方式编写位置坐标转换及传输节点 前言 在配置mid360运行环境后&#xff0c;可使用mid360进行室内的精准定位。 环境配置 在livox_ros_driver2的上级目录src下保存fast-lio的工程 git clone https://github.com/hku-mars/F…

在Ubuntu20.04(原为cuda12.0, gcc9.几版本和g++9.几版本)下先安装cuda9.0后再配置gcc-5环境

因为自己对Linux相关操作不是很熟悉&#xff0c;所以因为之前的代码报错之后决定要安cuda9.0&#xff0c;于是先安装了cuda9.0。里面用到的一些链接&#xff0c;链接文件夹时直接去copy它的路径&#xff0c;就不那么容易错了。 今天运行程序之后发现gcc环境不太匹配cuda9.0&am…

2024/03/19(网络编程·day5)

一、思维导图 二、selec函数实现TCP并发服务器 #include<myhead.h>#define SER_PORT 8888 //服务器端口号 #define SER_IP "192.168.117.116" //服务器IP int main(int argc, const char *argv[]) {//1、创建一个套接字int sfd -1;sfd socket(AF_INET,SOC…

Vue技能树总结01

Vue vs React 相似之处: 它们都有使用 Virtual DOM&#xff1b;提供了响应式&#xff08;Reactive&#xff09;和组件化&#xff08;Composable&#xff09;的视图组件。将注意力集中保持在核心库&#xff0c;而将其他功能如路由和全局状态管理交给相关的库。React 比 Vue 有更…