同步互斥机制和编程方法

同步互斥机制和编程方法

文章目录

  • 同步互斥机制和编程方法
    • 一、前言
    • 二、同步互斥机制
      • 2.1 概念回顾
      • 2.2 竞态条件(race condition)
        • 2.2.1 概述
        • 2.2.2 解决方法
      • 2.3 具体做法及其编程
        • 2.3.1 忙等互斥
        • 2.3.2 睡眠与唤醒(软硬件结合)
    • 三、小结

一、前言

同步互斥到底是怎样产生的呢?我们一起借助编程来探索一下吧~

二、同步互斥机制

2.1 概念回顾

  • 同步:谁先做

    比如:编辑器的词频检测

  • 互斥:一个做的时候,另一个不要打扰

2.2 竞态条件(race condition)

2.2.1 概述

两个或多个线程同时对一共享数据进行修改,影响程序运行的正确性。这也是产生同步互斥的原因

2.2.2 解决方法
  • 禁止多个线程同一时刻对共享资源进行读写(不推荐,本质就是实现多个任务互相调度)

    共享资源:共享文件、共享内存(多线程易引发冲突)

  • 临界区

    • 任何时候两个进程不能同时处于临界区(任何一个任务都只能独占临界区)
    • 不应对CPU的速度和数量做任何假设(CPU的速度和数量是随机的,任务执行是随机的)
    • 位于临界区的进程不得阻塞其他进程
    • 不能使任何进程无限等待进入临界区

针对上述提出了4个遵循的原则(偏理论性)

遵循的原则

  • 空闲让进:临界区空闲时,应允许一个进程访问

  • 忙则等待:临界区正在被访问时,其他试图访问的进程需要等待

  • 有限等待:要在有限时间内进入临界区,保证不饥饿

  • 让权等待:进不了临界区的进程,要释放处理机,防止忙等

    防止轮询耗费资源,纯软不能实现让权

2.3 具体做法及其编程

重要的概念:

  • 阻塞:睡眠(队列维护)
  • 忙等:自旋锁(用户用不到,内核用,内核才知道这个资源是快速设备还是慢速设备)

OS:

  • 正在执行的任务和阻塞的任务抢占CPU
  • 阻塞的任务睡觉去了,等待正在执行的任务执行完唤醒CPU
2.3.1 忙等互斥

在现代OS中,忙等互斥多使用在小时间事件

  • 屏蔽中断(纯硬件·最直接)

    每个进程在进入临界区后立即屏蔽所有中断(但是千万不要忘记打开

    缺点

    • 屏蔽中断时间很长,CPU不能调度,很多任务响应不了
    • 如果屏蔽过程中出现错误,但是时钟中断被屏蔽,容易陷入死机

    方案的可行性

    • 进程进入临界区是由谁来决定的?

      如果是用户进程,全凭用户意愿,当进程进入临界区后,用户进程关闭中断,如果经过一段较长时间后,进程没有离开,那么中断就一直启动不了,会有什么问题?答:黑客用户就很危险,因此绝对不会开放给用户

      内核来说,当它执行更新变量或列表的几条指令期间将中断屏蔽是很方便的

    • 多核CPU屏蔽中断不可行

      一套汇编指令实现只屏蔽一个CPU,可能会导致其他CPU可以运行,仍然会有冲突

    应用

    单核CPU的快速事件

  • 锁变量(纯软件)

    锁:

    • 自旋锁(spin_lock):忙等锁,不会放弃CPU,轮询CPU,while(),适合小周期的小等待
    • 互斥锁(mutex):阻塞行为,一旦发现资源不可用,睡眠-放弃CPU,最终还是要获得CPU,被另外的程序断唤醒,CPU调度(睡眠和唤醒会用)

    Linux用一般是互斥锁,自旋锁一般是内核用,用户一般用不到

    这里的锁变量是指自旋锁

    先设置一把锁,锁变量等于0(没锁)。现在,进程A在t时刻时被CPU调度了,这时进程A就先判断一下锁是否等于0(有没有人用),如果等于0(没有人用)马上设置为1,t2时刻,进程B尝试进入临界区了,就循环判断lock等不等于0,while(lock == 1);,红色的阻塞就代表一直轮询CPU,红色和蓝色一直抢CPU(但是分时的话就会都能用得到),一直到进程A离开临界区,lock = 0;进程B立刻设置lock = 1;

    编码模拟

    intlock=0;// 临界区代码段(外面)externvoidcritical_region();// 非临界区的代码段externvoidnoncritical_region();voidprocess0(){while(1){// 进入临界区// 判断是否有锁,如果没有锁,死循环等待锁被释放while(lock);// 判断:先从内存中取值,边取边判断// 加锁lock=1;critical_region();// 释放锁lock=0;noncritical_region();}}voidprocess1(){while(1){// 进入临界区// 判断是否有锁,如果没有锁,死循环等待锁被释放while(lock);// 加锁lock=1;critical_region();// 释放锁lock=0;noncritical_region();}}

    缺点

    lock = 0;准备设置为1时,时间片到了,被进程B抢占了lock = 0;也开始设置为1,时间片又到了,大家一运行就会出问题。

    原子操作

    刚刚写的代码具有原子性(Atomicity)(要不然读完,要不然写完,在读写的过程中是不允许被打断的)怎么实现原子变量

    有些硬件中没有办法实现,早期没有硬件帮忙时,实现原子变量还是得借助内存,这时自旋锁应运而生

    怎么实现自旋锁

    封装了两个接口:spin_lock(&lcok);codespin_unlock(&lock);。CPU不支持汇编,直接写的话,关中断,写入or读取,开中断(spin_lock(&lcok);

    虽说是原子性,可以通过关中断的方法实现原子性,原子性的目的就是关中断,现在采用专门的指令集(TSL):测试并设置、比较并交换(软件靠不了,只能靠硬件),接口还是不变

  • 严格轮询法(纯软件)

    单标志法轮询方式

    编码模拟

    intturn;// 表示当前允许进入临界区的进程号// 临界区代码段(外面)externvoidcritical_region();// 非临界区的代码段externvoidnoncritical_region();voidprocess0(){while(1){// 准备进入临界区,轮询判断当前进程能否进入while(turn==0){// 执行临界区critical_region();turn=1;// 标记当前可以进入临界区的是进程1noncritical_region();}}}voidprocess1(){while(1){// 准备进入临界区,轮询判断当前进程能否进入while(turn==1){// 执行临界区critical_region();turn=0;// 标记当前可以进入临界区的是进程1noncritical_region();}}}

    turn等于谁谁就能运行

    缺点

    进程1执行完,就会出现进入非临界区等待(时间很长),这时运行进程2,但是进程2非常快,执行完毕后,仍然还是进程1在非临界区,这时候就不能再进入进程2,违背了“空闲让进”原则

  • Peterson解法(纯软件)

    类型

    • 谦让型

      主动争取,主动谦让,检查,且最好后一次是谁谦让

    • 主动自信型

      一般不用

    编码模拟

    #defineFALSE0#defineTRUE1// 临界区代码段(外面)externvoidcritical_region();// 非临界区的代码段externvoidnoncritical_region();intturn;// 记录当前“轮到”哪个进程进入临界区intinterested[2];// 记录每个进程是否愿意进入临界区voidenter_region(intprocess){intother=1-process;// 进程编号就是0或1interested[process]=TRUE;// 标记本进程希望进入临界区turn=other;// 尝试将turn设置为另一个进程的编号// 等待条件:检查对方是否也想使用,且最后一次是谦让的(就代表谁最后执行)while(interested[other]==TRUE&&turn==other);}voidleave_region(intprocess){// 标记本进程已经离开临界区interested[process]=FALSE;}voidprocess0(){do{enter_region(0);critical_region();leave_region(0);noncritical_region();}while(TRUE);}voidprocess1(){do{enter_region(1);critical_region();leave_region(1);noncritical_region();}while(TRUE);}

    遵循空闲让进、忙则等待、有限等待,未遵循让权等待

  • TSL指令、XCHG指令(纯硬件)

    纯靠硬件实现锁的问题,都是原子操作,可以实现多CPU操作

    TSL

    • 读取与锁定

      指令从指定的内存中读取当前值,将这个值加载到寄存器RX中,若0,在内存里写1,加锁;否则一直读,然后进入临界区干活,干完释放锁,归0

    XCHG:主要是x86使用

    交换寄存器和内存位置,在寄存器放1,将寄存器中的1给lock,lock原来的值给寄存器(lock永远等于1),检查寄存器的值(判断锁是否被设置),如果不等于0,继续尝试enter_region,成功取锁后,进入临界区执行代码,执行完离开临界区,释放锁

2.3.2 睡眠与唤醒(软硬件结合)

安卓、IOS使用这种软硬件结合很多

睡眠和唤醒多用在长时间事件上

弊端:睡眠就需要队列、保护、切换、存储等,这些也是需要消耗时间的,当这个时间占大头时,就得不偿失了。

三、小结

首先明确同步和互斥的根本内涵,然后明确竞态条件是产生同步互斥的原因以及有关竞态条件的解决方案。解决方案围绕两大块:忙等互斥和睡眠与唤醒。忙等互斥的种种方法都是围绕四大原则来的,从软硬件不同角度思考解决之道。

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

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

相关文章

程序员必读:2026年AI智能体趋势,收藏这篇抢占先机

Google Cloud《2026 AI智能体趋势报告》揭示五大趋势:人人拥有智能体释放创造力、构建企业数字流水线、重塑礼宾式客户体验、实现安全主动防御、通过人才升级驱动价值。AI智能体正从"工具赋能"转向"生态重构",不仅提升效率&#xff…

Windows 系统版本转换工具,一键互转不用重装

前言今天分享一款Windows 系统版本一键转换工具,它无需重装系统,就能一键转换系统版本,如专业版转家庭版、家庭版转企业版,Win10/Win11 系统都支持,整个过程保留原有数据,操作简单。软件介绍1、 右键点击程…

大数据领域数据治理的质量提升秘籍

大数据领域数据治理的质量提升秘籍:从理论到实战的全链路指南 一、为什么数据质量是大数据的“生命线”? 在某电商公司的季度复盘会上,推荐算法团队负责人脸涨得通红:“过去3个月,我们的推荐转化率下降了30%——原因居…

深入理解 MCP,非常详细收藏我这一篇就够了

如何系统的学习大模型 AI ? 由于新岗位的生产效率,要优于被取代岗位的生产效率,所以实际上整个社会的生产效率是提升的。 但是具体到个人,只能说是: “最先掌握AI的人,将会比较晚掌握AI的人有竞争优势”…

大模型Agent架构演进:从临时拼接到按需组合的微应用之路(程序员必收藏)

文章阐述了Agent系统架构从ad-hoc临时型Agent向标准化能力再向按需组合的just-in-time微应用/界面的主流演进路线。这种演进解决了ad-hoc模式在治理、复用、安全方面的问题,通过标准化协议(MCP、A2A)和JIT身份权限管理,实现开发效率提升、运营治理优化和…

AI产品经理与大模型学习全攻略:从入门到精通,零基础也能掌握AI思维

文章系统介绍了AI产品经理与传统产品经理的区别,强调AI思维的重要性。详细解析了AI产业链结构(基础层、技术层、应用层)和AI产品经理的四象限分类(突破型、创新型、应用型、普及型)。提供了从初阶到高阶的大模型AI学习…

根据算法题目时间限制推算时间复杂度限制

核心思路:先明确基准值首先要建立一个基础认知:普通计算机在 1 秒内,大约能执行 1 亿(10^8)次 基本运算(比如加减乘除、变量赋值、条件判断等)。这个数值是经验值,不同评测机可能略有…

AI大模型学习路线:从入门到高薪,程序员收藏必备!2025年AI就业薪资表曝光

文章讲述AI领域特别是大模型方向的就业前景。科技巨头如腾讯、阿里、Meta等大力布局AI,导致人才紧缺,薪资飙升。2025年AI岗位需求增长10倍,核心技术岗供需比低至0.39。大模型研发、端侧推理等复合型人才尤为抢手,建议技术党深耕核…

FPGA应用开发和仿真【3.7】

8.5 混频和相干解调混频,即两个信号做乘法,是在数字通信中很常用的信号处理方法。考虑两个单频信号Acos(ω1t 1)和cos(ω0t),一般前者为待处理的信号,而后者为已知的参考信号&#x…

每日Java面试场景题知识点之-ELK技术栈实战应用

每日Java面试场景题知识点之-ELK技术栈实战应用 前言 在现代Java企业级项目中,日志分析是系统监控和故障排查的重要环节。ELK技术栈(Elasticsearch、Logstash、Kibana)作为目前最流行的日志分析解决方案,在Java项目中得到了广泛应…

【毕业设计】SpringBoot+Vue+MySQL “衣依”服装销售平台平台源码+数据库+论文+部署文档

💡实话实说:有自己的项目库存,不需要找别人拿货再加价,所以能给到超低价格。摘要 随着互联网技术的快速发展和电子商务的普及,线上服装销售平台逐渐成为消费者购物的主要渠道之一。传统线下服装销售模式受限于时间和空…

每日Java面试场景题知识点之-ELK日志分析

场景题:微服务架构下日志分散导致故障排查困难 问题描述 在一家大型电商平台的微服务架构中,系统包含订单服务、用户服务、支付服务、库存服务等20多个微服务实例,每个服务部署在多台服务器上。某天凌晨,用户支付功能出现异常&…

FPGA应用开发和仿真【3.8】

8.8.3 调制解调仿真 仿真模拟的系统与AM仿真时类似,结构如图8-32所示。 图8-32 WBFM调制解调仿真系统结构 代码8-16是测试平台。 代码8-16 WBFM调制解调系统测试平台 图8-33所示是一段仿真波形。解调器工作建立时输出了一段不正确的波形。 图8-33 WBFM测试平台仿…

FPGA应用开发和仿真【3.6】

7.8 PID控制器 PID控制器广泛用于控制系统,控制系统中的数字控制部分也是数字信号处理系统的一种。典型的数字PID控制器如图7-63所示,它由前向欧拉法转换连续时间PID控制器而来,其P、I、D三个参数,分别为比例、积分、微分系数,而N用于配置微分单元中滤波器的极点,将有助…

从零到AIGC产品经理,2个月上岸全攻略,小白也能学会

本文分享了一套2个月成功转行AIGC产品经理的实用指南,涵盖八个关键步骤:获取行业资讯与研报、选择细分领域并搭建知识库、系统掌握AIGC基础知识、完成实战项目、撰写融合项目经验的简历、准备面试高频问题。通过文本生成和图片生成两类实战项目&#xff…

Java Web 墙绘产品展示交易平台系统源码-SpringBoot2+Vue3+MyBatis-Plus+MySQL8.0【含文档】

💡实话实说:有自己的项目库存,不需要找别人拿货再加价,所以能给到超低价格。摘要 随着互联网技术的快速发展和艺术市场的不断扩大,墙绘艺术作为一种独特的装饰形式,逐渐受到大众的青睐。传统的墙绘交易方式…

收藏这篇!小白也能学会的AI知识库搭建全攻略

本文详细介绍如何使用AnythingLLM和DeepSeek R1搭建个人AI知识库,解决AI回答不准确的痛点。从下载安装、配置API、上传文档到知识检索问答,提供完整步骤指导。该方法简单高效、成本低廉,可创建可靠安全的私有知识库,大幅提升学习和…

国内首次开源灵巧操作数据集!填补具身智能数据空白!

如果你觉得现在的机器人已经很聪明,那你大概率还没见过它们“拿纸杯”、“拆纸箱”时手忙脚乱的样子。在仿真环境里,机器人抓什么都稳;可一到真实世界,纸杯一捏就扁、快递一夹就滑,仿佛一夜回到解放前。问题出在哪&…

什么是proxy

在前端开发中,Proxy 是 ES6 引入的一个高级特性,用于拦截和自定义对象的基本操作(如属性访问、赋值、枚举、函数调用等)。它为开发者提供了元编程能力,是实现响应式系统、数据校验、访问控制等功能的核心技术。 一、基…

收藏这篇就够了!DeepSeek+RAG本地知识库搭建实战,小白也能上手的大模型教程

DeepSeekRAG本地知识库技术结合了DeepSeek大模型与检索增强生成(RAG)技术,旨在构建高效智能的本地化知识库系统。DeepSeek具备强大自然语言处理能力,能理解和生成文本;RAG技术通过结合信息检索和文本生成,使模型在生成文本时可参考…