当前位置:首页 > 科技  > 软件

我们一起聊聊从操作系统层面理解多线程冲突

来源: 责编: 时间:2024-04-19 09:28:05 89观看
导读前言今天来从操作系统层面理解一下多线程冲突的问题,话不多说,开始~~什么是多线程的冲突同一进程内的线程是共享同一内存空间的,所以在多个线程的进程里,线程是可以同时操作这个进程空间的数据的,线程之间可以共享进程的资

前言

今天来从操作系统层面理解一下多线程冲突的问题,话不多说,开始~~vgu28资讯网——每日最新资讯28at.com

vgu28资讯网——每日最新资讯28at.com

什么是多线程的冲突

同一进程内的线程是共享同一内存空间的,所以在多个线程的进程里,线程是可以同时操作这个进程空间的数据的,线程之间可以共享进程的资源:比如代码段、堆空间、数据段、打开的文件等资源,但每个线程也有自己独立的栈空间。如果多个线程如果竞争共享资源,如果不采取有效的措施,则会造成共享数据的混乱。vgu28资讯网——每日最新资讯28at.com

举个小栗子:一个房子里(代表一个进程),只有一个厕所(代表共享资源)。屋子里面有两个人A和B(代表两个线程),共用这个厕所。一天A去上厕所了,不过厕所门的锁坏了,就没法锁门。这是B也想去上厕所,直接就开门进去了,然后发现A在里面。vgu28资讯网——每日最新资讯28at.com

上面这个故事说明,对于共享资源,如果没有上锁,在多线程的环境里,那么就可能会发生翻车现场。vgu28资讯网——每日最新资讯28at.com

竞争与协作

做个小实验,创建五个线程,它们分别对共享变量 i 自增 1 执行 1000 次vgu28资讯网——每日最新资讯28at.com

package com.atguigu.juc.atomics;public class Station{    int i = 0;    public void add() {        for(int m = 0; m < 1000; m++){            try {                //使用sleep()模拟业务时间,如果不加,大概率不会出现并发问题                Thread.sleep(1);                i += 1;            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }    public static void main(String[] args) throws InterruptedException {        //实例化站台对象,并为每一个站台取名字        Station station = new Station();        new Thread(station::add,"线程1").start();        new Thread(station::add,"线程2").start();        new Thread(station::add,"线程3").start();        new Thread(station::add,"线程4").start();        new Thread(station::add,"线程5").start();        Thread.sleep(20000);        // 让每一个站台对象各自开始工作        System.out.println(station.i);        Thread.sleep(5000);        System.out.println(station.i);    }}

运行了几次发现,每次运行得到不同的结果。在计算机里是不能容忍的,虽然是小概率出现的错误,但是小概率事件它一定是会发生的。vgu28资讯网——每日最新资讯28at.com

为什么会出现这样的问题呢?vgu28资讯网——每日最新资讯28at.com

为了理解为什么会发生这种情况,我们必须了解编译器为更新计数器 i 变量生成的代码序列,也就是要了解汇编指令的执行顺序。vgu28资讯网——每日最新资讯28at.com

在这个例子中,我们只是想给 i 加上数字 1,那么它对应的汇编指令执行过程是这样的:vgu28资讯网——每日最新资讯28at.com

vgu28资讯网——每日最新资讯28at.com

可以发现,只是单纯给 i 加上数字 1,在 CPU 运行的时候,实际上要执行 3 条指令。vgu28资讯网——每日最新资讯28at.com

设想我们的线程 1 进入这个代码区域,它将 i 的值(假设此时是 50 )从内存加载到它的寄存器中,然后它向寄存器加 1,此时在寄存器中的 i 值是 51。vgu28资讯网——每日最新资讯28at.com

现在,一件不幸的事情发生了:当前线程被挂起了,线程 2 被调度运行,并进入同一段代码。它也执行了第一条指令,从内存获取 i 值并将其放入到寄存器中,此时内存中 i 的值仍为 50,因此线程 2 寄存器中的 i 值也是 50。假设线程 2 执行接下来的两条指令,将寄存器中的 i 值 + 1,然后将寄存器中的 i 值保存到内存中,于是此时全局变量 i 值是 51。vgu28资讯网——每日最新资讯28at.com

最后,又发生一次上下文切换,线程 1 恢复执行。还记得它已经执行了两条汇编指令,现在准备执行最后一条指令。回忆一下, 线程 1 寄存器中的 i 值是51,因此,执行最后一条指令后,将值保存到内存,全局变量 i 的值再次被设置为 51。vgu28资讯网——每日最新资讯28at.com

简单来说,增加 i (值为 50 )的代码被运行两次,按理来说,最后的 i 值应该是 52,但是由于不可控的调度,导致最后 i 值却是 51。vgu28资讯网——每日最新资讯28at.com

针对上面线程 1 和线程 2 的执行过程,我画了一张流程图,会更明确一些:vgu28资讯网——每日最新资讯28at.com

vgu28资讯网——每日最新资讯28at.com

互斥的概念

上面展示的情况称为竞争条件(race condition),当多线程相互竞争操作共享变量时,由于运气不好,即在执行过程中发生了上下文切换,我们得到了错误的结果,事实上,每次运行都可能得到不同的结果,因此输出的结果存在不确定性(indeterminate)。vgu28资讯网——每日最新资讯28at.com

由于多线程执行操作共享变量的这段代码可能会导致竞争状态,因此我们将此段代码称为临界区(critical section),它是访问共享资源的代码片段,一定不能给多线程同时执行。vgu28资讯网——每日最新资讯28at.com

我们希望这段代码是互斥(mutualexclusion)的,也就说保证一个线程在临界区执行时,其他线程应该被阻止进入临界区,说白了,就是这段代码执行过程中,最多只能出现一个线程。vgu28资讯网——每日最新资讯28at.com

vgu28资讯网——每日最新资讯28at.com

另外,说一下互斥也并不是只针对多线程。在多进程竞争共享资源的时候,也同样是可以使用互斥的方式来避免资源竞争造成的资源混乱。vgu28资讯网——每日最新资讯28at.com

同步的概念

所谓同步,就是并发进程/线程在一些关键点上可能需要互相等待与互通消息,这种相互制约的等待与互通信息称为进程/线程同步。vgu28资讯网——每日最新资讯28at.com

上面那个栗子:一A去上厕所了,发现厕所门的锁坏了,告诉B一声。这是B想去上厕所的话,就会先问一下A是不是还在里面,然后再开门进去了。这也是互通消息的方式,如果锁没有坏,A直接把门锁上,这就是相互等待的方式。vgu28资讯网——每日最新资讯28at.com

怎么解决多线程冲突?

为了实现进程/线程间正确的协作,操作系统必须提供实现进程协作的措施和方法,主要的方法有两种:vgu28资讯网——每日最新资讯28at.com

  • 锁:加锁、解锁操作;
  • 信号量:P、V 操作;

这两个都可以方便地实现进程/线程互斥,而信号量比锁的功能更强一些,它还可以方便地实现进程/线程同步。vgu28资讯网——每日最新资讯28at.com

使用加锁操作和解锁操作可以解决并发线程/进程的互斥问题。vgu28资讯网——每日最新资讯28at.com

任何想进入临界区的线程,必须先执行加锁操作。若加锁操作顺利通过,则线程可进入临界区;在完成对临界资源的访问后再执行解锁操作,以释放该临界资源。vgu28资讯网——每日最新资讯28at.com

vgu28资讯网——每日最新资讯28at.com

信号量

信号量是操作系统提供的一种协调共享资源访问的方法。通常信号量表示资源的数量,对应的变量是一个整型(sem)变量。vgu28资讯网——每日最新资讯28at.com

另外,还有两个原子操作的系统调用函数来控制信号量的,分别是:vgu28资讯网——每日最新资讯28at.com

  • P 操作:将 sem 减 1,相减后,如果 sem < 0,则进程/线程进入阻塞等待,否则继续,表明 P 操作可能会阻塞;
  • V 操作:将 sem 加 1,相加后,如果 sem <= 0,唤醒一个等待中的进程/线程,表明 V 操作不会阻塞;

举个类比,2 个资源的信号量,相当于 2 条火车轨道,PV 操作如下图过程:vgu28资讯网——每日最新资讯28at.com

vgu28资讯网——每日最新资讯28at.com


vgu28资讯网——每日最新资讯28at.com

本文链接://www.dmpip.com//www.dmpip.com/showinfo-26-84017-0.html我们一起聊聊从操作系统层面理解多线程冲突

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: C#中的正则表达式:强大的文本处理工具

下一篇: WPF界面魔法:探秘Template奇妙世界,个性化定制你的UI

标签:
  • 热门焦点
  • 一加Ace2 Pro真机揭晓 钛空灰配色质感拉满

    一加Ace2 Pro真机揭晓 钛空灰配色质感拉满

    终于,在经过了几波预热之后,一加Ace2 Pro的外观真机图在网上出现了。还是博主数码闲聊站曝光的,这次的外观设计还是延续了一加11的方案,只是细节上有了调整,例如新加入了钛空灰
  • 《英雄联盟》夏季赛总决赛今日开打!JDG对阵LNG首发名单来了 Knight:准备三连冠

    《英雄联盟》夏季赛总决赛今日开打!JDG对阵LNG首发名单来了 Knight:准备三连冠

    8月5日消息,今日17:00,《英雄联盟》2023LPL夏季赛总决赛将正式开打,由JDG对阵LNG。对两支队伍来说,这场比赛不仅要争夺夏季赛冠军,更要决定谁才是LPL赛区一
  • K6:面向开发人员的现代负载测试工具

    K6:面向开发人员的现代负载测试工具

    K6 是一个开源负载测试工具,可以轻松编写、运行和分析性能测试。它建立在 Go 和 JavaScript 之上,它被设计为功能强大、可扩展且易于使用。k6 可用于测试各种应用程序,包括 Web
  • 微信语音大揭秘:为什么禁止转发?

    微信语音大揭秘:为什么禁止转发?

    大家好,我是你们的小米。今天,我要和大家聊一个有趣的话题:为什么微信语音不可以转发?这是一个我们经常在日常使用中遇到的问题,也是一个让很多人好奇的问题。让我们一起来揭开这
  • JavaScript学习 -AES加密算法

    JavaScript学习 -AES加密算法

    引言在当今数字化时代,前端应用程序扮演着重要角色,用户的敏感数据经常在前端进行加密和解密操作。然而,这样的操作在网络传输和存储中可能会受到恶意攻击的威胁。为了确保数据
  • 三万字盘点 Spring 九大核心基础功能

    三万字盘点 Spring 九大核心基础功能

    大家好,我是三友~~今天来跟大家聊一聊Spring的9大核心基础功能。话不多说,先上目录:图片友情提示,本文过长,建议收藏,嘿嘿嘿!一、资源管理资源管理是Spring的一个核心的基础功能,不
  • 本地生活这块肥肉,拼多多也想吃一口

    本地生活这块肥肉,拼多多也想吃一口

    出品/壹览商业 作者/李彦编辑/木鱼拼多多也看上本地生活这块蛋糕了。近期,拼多多在App首页&ldquo;充值中心&rdquo;入口上线了本机生活界面。壹览商业发现,该界面目前主要
  • 得物宠物生意「狂飙」,发力“它经济”

    得物宠物生意「狂飙」,发力“它经济”

    作者|花花小萌主近日,得物宣布正式上线宠物鉴别,通过得物App内的&ldquo;在线鉴别&rdquo;,可找到鉴别宠物的选项。通过上传自家宠物的部位细节,就能收获拥有专业资质认证的得物鉴
  • 机构称Q2国内智能手机销量同比下滑4% vivo份额重回第1

    机构称Q2国内智能手机销量同比下滑4% vivo份额重回第1

    7月29日消息,根据市场调查机构Counterpoint Research公布的最新报告,2023年第2季度中国智能手机销量同比下降4%,创新自2014年以来第2季度销量新低。报
Top
Baidu
map