014 Linux_同步

news2025/2/24 18:00:22

​🌈个人主页: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.coloradmin.cn/o/1529108.html

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

相关文章

Java面试题总结18之springcloud四种分布式事务解决方案

XA规范&#xff1a;分布式事务规范&#xff0c;规定了分布式事务模型 四个角色&#xff1a;事务管理器&#xff08;协调者TM&#xff09;&#xff0c;资源管理器&#xff08;参与者RM&#xff09;&#xff0c;应用程序AP&#xff0c;通信资源管理器CRM 全局事务&#xff1a;一…

微信小程序小白易入门基础教程1

微信小程序 基本结构 页面配置 页面配置 app.json 中的部分配置&#xff0c;也支持对单个页面进行配置&#xff0c;可以在页面对应的 .json 文件来对本页面的表现进行配置。 页面中配置项在当前页面会覆盖 app.json 中相同的配置项&#xff08;样式相关的配置项属于 app.js…

QML | JavaScript作用域和命名解析

#1 JavaScript作用域和命名解析 QML属性绑定、内联函数和导人的JavaScript文件都运行在一个JavaScript作用域中。作用域主要控制两点:一是表达式可以访问哪些变量;二是当两个或多个名字冲突时,哪个变量优先。由于JavaScript的内建作用域机制非常简单,QML对其进行了加强,使…

java实现kml文件下载接口

根据业务需求&#xff0c;需提供一个下载kml格式航线文件的HTTP GET接口 示例代码 package com.kyrielx.kmzdemo.controller;import org.apache.commons.io.FileUtils; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org…

3/13/24运算符、补码、整型、浮点型、汇编

目录 三目运算符 逗号运算符 自增自减运算符 位运算 运算符优先级 补码讲解 整型解析 溢出解析 浮点数IEEE754标准解析 浮点数精度丢失 真题 汇编指令 生成汇编方法 常用指令 三目运算符 条件运算符是C语言中唯一的三目运算符。通过判断问号之前的表达式的真假&…

linux之权限管理和组

一&#xff0c;ACL权限 1.1&#xff0c;什么是acl权限&#xff1f; ACL是Access Control List的缩写&#xff0c;即访问控制列表。可以通过下列的实例来理解ACL的作用&#xff1a; 思考如何实现如下的权限控制&#xff1a; 每个项目成员在有一个自己的项目目录&#xff0c;…

网工内推 | 信息安全主管,CISP认证优先,最高25K,加绩效提成

01 福建省数字福建云计算运营有限公司 招聘岗位&#xff1a;网络及信息安全主管 职责描述&#xff1a; 1.负责带领IT运维团队&#xff0c;对公司网络与安全整体架构规划&#xff0c;设计、运营及IT设备的全生命周期运维规划等&#xff1b; 2.负责对网络、网络安全的日常运维管…

【JavaScript】JavaScript 程序流程控制 ① ( 顺序流程控制 | 分支流程控制 )

文章目录 一、JavaScript 程序流程控制简介1、顺序流程控制2、分支流程控制3、分支流程控制 - 代码示例 一、JavaScript 程序流程控制简介 JavaScript 程序 执行过程中 , 不同的代码执行顺序 , 得到的结果是不同的 , 在编程中 经常 需要 根据 不同的条件 执行不同的代码块 , 或…

计算机缺失msvcp110.dll如何修复,多种修复方法教给你

当电脑系统中msvcp110.dll文件丢失时&#xff0c;可能会对计算机的正常运行产生一系列显著的影响。msvcp110.dll是Microsoft Visual C Redistributable Package的一部分&#xff0c;这个动态链接库文件对于许多基于Windows的应用程序至关重要&#xff0c;尤其是一些使用C编译器…

2024蓝桥杯每日一题(回溯)

备战2024年蓝桥杯 -- 每日一题 Python大学A组 试题一&#xff1a;木棒 试题二&#xff1a;n皇后问题 试题三&#xff1a;糖果 试题四&#xff1a;飞机降落 试题五&#xff1a;生日蛋糕 试题一&#xff1a;木棒 【问题描述】 乔治拿来一组等长…

【工具】Mermaid + 大模型画流程图

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 引入使用画TCP三次握手了解历史人物 总结 引入 最近看面试文章关于TCP三次握手和…

PTA L2-021 点赞狂魔

微博上有个“点赞”功能&#xff0c;你可以为你喜欢的博文点个赞表示支持。每篇博文都有一些刻画其特性的标签&#xff0c;而你点赞的博文的类型&#xff0c;也间接刻画了你的特性。然而有这么一种人&#xff0c;他们会通过给自己看到的一切内容点赞来狂刷存在感&#xff0c;这…

好委屈,东方甄选为何总是被供应商骗?

东方甄选最近很委屈。 315晚会过后&#xff0c;知名打假人王海爆料&#xff0c;称315晚会曝光的槽头肉扣肉在东方甄选和小杨哥的直播间里销售过。 东方甄选赶忙去问了问供应商情况。 供应商的回答让他感到暖心&#xff0c;表示虽然315晚会曝光了我们公司违规使用糟头肉&…

Pulsar IO实战

一、引言 今天跟着 官方文档 基于docker玩一把Pulsar IO吧 二、概要 在用户能够轻松的将消息队列跟其他系统(数据库、其他消息系统)一起使用时&#xff0c;消息队列的作用才是最强大的。而Pulsar IO connectors可以让你很轻松的创建、部署以及管理这些跟外部系统的连接&#…

Golang 开发实战day04 - Standard Library

Golang 开发实战day04 - Standard Library 接下来开始我们第四天学习&#xff0c;Go语言标准库提供了丰富的功能&#xff0c;可以帮助开发者快速完成各种任务。 golang就像其他语言一样&#xff0c;附带了一些非常轻量级的函数和特性&#xff0c;都是开箱即用的&#xff0c;这里…

KMM初探

什么是KMM&#xff1f; 在开始使用 KMM 之前&#xff0c;您需要了解 Kotlin。 KMM 全称&#xff1a;Kotlin Multiplatform Mobile&#xff09;是一个用于跨平台移动开发的 SDK,相比于其他跨平台框架&#xff0c;KMM是原生UI逻辑共享的理念,由KMM封装成Android(Kotlin/JVM)的aar…

第四百一十一回

文章目录 1. 概念介绍2. 思路与方法2.1 实现思路2.2 实现方法 3. 示例代码4. 内容总结 我们在上一章回中介绍了"给geolocator插件提交问题的结果"相关的内容&#xff0c;本章回中将介绍自定义标题栏.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 我…

第四百一十二回

文章目录 1. 概念介绍2. 思路与方法2.1 实现思路2.2 实现方法 3. 示例代码4. 内容总结 我们在上一章回中介绍了"给geolocator插件提交问题的结果"相关的内容&#xff0c;本章回中将介绍自定义标题栏.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 我…

我的自建博客之旅04之Halo

我的自建博客之旅04之Halo Halo是我无意间发现的一款博客框架,如果你讨厌Hexo,Vuepress等静态框架本地编辑,构建部署等方式,如果你想要一款一次搭建,前台是博客,后台是文章维护,并且支持各种定制化折腾的博客框架,可能Halo会比较适合你。 因为我个人还是比较偏技术,…

八节【DBA从入门到实践】课程,带你快速掌握OceanBase运维管理核心技能

为帮助用户及开发者更好、更快地掌握OceanBase DBA核心技能&#xff0c;OceanBase社区设计了配套教程——“DBA从入门到实践”。8期教程带大家循序渐进掌握OceanBase运维管理核心技能。搭配随堂习题和OceanBase技术专家在线答疑&#xff0c;快速掌握重要知识点&#xff0c;并轻…