3、共享模型之管程 -- 3.1、共享带来的问题

2024-06-12 05:32

本文主要是介绍3、共享模型之管程 -- 3.1、共享带来的问题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1、共享带来的问题

小故事

  • 老王(操作系统)有一个功能强大的算盘(CPU),现在想把它租出去,赚一点外快
  • 在这里插入图片描述
  • 小南、小女(线程)来使用这个算盘进行一些计算,并按照时间给老王支付费用
  • 但小南不能一天24小事使用算盘,他经常要小憩一会儿(sleep),又或者是去吃饭上厕所(阻塞io操作),有时还需要一根烟,没烟的时候思绪全无(wait),这些情况称为阻塞
  • 在这里插入图片描述
  • 在这些时候,算盘没有利用起来(不能收钱了),老王觉得有点不划算
  • 另外,小女也想用用算盘,如果总是让小南占着算盘,小女觉得不公平
  • 于是,老王灵机一动,想了个办法[让他们每个人用一会,轮流着使用算盘]
  • 这样,小南阻塞的时候,算盘可以分给小女使用,反之亦然
  • 最近执行的计算比较复杂,需要存储一些中间结果,而学生们的脑容量(工作内存)不够,所以老王申请了一个笔记本(主内存),把一些中间结果先记在本上
  • 计算流程是这样的
  • 在这里插入图片描述
  • 但是由于分时系统,有一天还是发生了事故
  • 小南刚读取到初始值0做了个+1运算,还没来得及写会结果
  • 老王说[小南,你的时间到了,该别人了,记住结果走吧],于是小南念叨着[结果是1,结果是1…],不甘心的到一边待着去了(上下文切换)
  • 老王说[小女,该你了],小女看到笔记本上还写着0做了个-1运算,将结果-1写入笔记本
  • 这时小女的时间也用完了,老王又叫醒了小南[小南,把你上次的题目算完吧],小南将他脑中的结果1写入了笔记本
  • 在这里插入图片描述
  • 小南和小女都觉得自己没做错,单笔记本里的结果是1而不是0

Java的体现

两个线程对初始值为0的静态变量一个做自增,一个做自建,各做5000次,结果是0吗?

    static int counter = 0;static final int times = 5000;public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(() -> {for (int i = 0; i < times; i++) {counter++;}}, "t1");Thread t2 = new Thread(() -> {for (int i = 0; i < times; i++) {counter--;}}, "t2");t1.start();t2.start();t1.join();t2.join();log.debug("结果:{}", counter);}

输出

2022/03/04-00:15:33.287 [main] c.Test1 - 结果:332

问题分析
以上的结果可能是正数、负数、零。为什么呢?因为Java中对静态变量的自增、自减并不是原子操作,要彻底理解,必须从字节码来进行分析。
例如对于i++而言(i为静态变量),事假会产生如下的JVM字节码指令:

getstatic i // 获取静态变量i的值
iconst_1 // 准备常量1
iadd // 自增
putstatic i // 将修改后的值存入静态变量i

而对应i--也是类似的:

getstatic i // 获取静态变量i的值
iconst_1 // 准备常量1
isub // 自减
putstatic i // 将修改后的值存入静态变量i

Java的内存模型如下,完成静态变量的自增、自减需要在主内存和工作内存中进行数据交换(这块会在别的章节进行叙述):
在这里插入图片描述
如果单线程,以上8行代码是顺序执行(不会交错)没有问题:
在这里插入图片描述
但多线程下这8航大吗可能交错运行:
出现负数的情况:
在这里插入图片描述
出现正数的情况:
在这里插入图片描述

临界区 Critical Section

  • 一个程序运行多个线程本身是没有偶问题的
  • 问题出在多个线程访问共享资源
    • 多个线程读共享资源其实也没有问题
    • 在多个线程对共享资源读写操作时发生指令交错,就会出现问题
  • 一段代码内如果存在对共享资源的多线程读写操作,称这段代码为临界区
    例如,下面代码中的临界区
static int counter = 0;
static void increment() 
// 临界区
{counter++;
}
static void decrement() 
// 临界区
{counter--;
}

竞态条件 Race Condition

多个线程在临界区内执行,由于代码的执行序列不同而导致结果无法预测,称之发生了竞态条件

这篇关于3、共享模型之管程 -- 3.1、共享带来的问题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1053320

相关文章

MybatisGenerator文件生成不出对应文件的问题

《MybatisGenerator文件生成不出对应文件的问题》本文介绍了使用MybatisGenerator生成文件时遇到的问题及解决方法,主要步骤包括检查目标表是否存在、是否能连接到数据库、配置生成... 目录MyBATisGenerator 文件生成不出对应文件先在项目结构里引入“targetProje

C#使用HttpClient进行Post请求出现超时问题的解决及优化

《C#使用HttpClient进行Post请求出现超时问题的解决及优化》最近我的控制台程序发现有时候总是出现请求超时等问题,通常好几分钟最多只有3-4个请求,在使用apipost发现并发10个5分钟也... 目录优化结论单例HttpClient连接池耗尽和并发并发异步最终优化后优化结论我直接上优化结论吧,

NFS实现多服务器文件的共享的方法步骤

《NFS实现多服务器文件的共享的方法步骤》NFS允许网络中的计算机之间共享资源,客户端可以透明地读写远端NFS服务器上的文件,本文就来介绍一下NFS实现多服务器文件的共享的方法步骤,感兴趣的可以了解一... 目录一、简介二、部署1、准备1、服务端和客户端:安装nfs-utils2、服务端:创建共享目录3、服

Java内存泄漏问题的排查、优化与最佳实践

《Java内存泄漏问题的排查、优化与最佳实践》在Java开发中,内存泄漏是一个常见且令人头疼的问题,内存泄漏指的是程序在运行过程中,已经不再使用的对象没有被及时释放,从而导致内存占用不断增加,最终... 目录引言1. 什么是内存泄漏?常见的内存泄漏情况2. 如何排查 Java 中的内存泄漏?2.1 使用 J

Golang的CSP模型简介(最新推荐)

《Golang的CSP模型简介(最新推荐)》Golang采用了CSP(CommunicatingSequentialProcesses,通信顺序进程)并发模型,通过goroutine和channe... 目录前言一、介绍1. 什么是 CSP 模型2. Goroutine3. Channel4. Channe

numpy求解线性代数相关问题

《numpy求解线性代数相关问题》本文主要介绍了numpy求解线性代数相关问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 在numpy中有numpy.array类型和numpy.mat类型,前者是数组类型,后者是矩阵类型。数组

解决systemctl reload nginx重启Nginx服务报错:Job for nginx.service invalid问题

《解决systemctlreloadnginx重启Nginx服务报错:Jobfornginx.serviceinvalid问题》文章描述了通过`systemctlstatusnginx.se... 目录systemctl reload nginx重启Nginx服务报错:Job for nginx.javas

Redis缓存问题与缓存更新机制详解

《Redis缓存问题与缓存更新机制详解》本文主要介绍了缓存问题及其解决方案,包括缓存穿透、缓存击穿、缓存雪崩等问题的成因以及相应的预防和解决方法,同时,还详细探讨了缓存更新机制,包括不同情况下的缓存更... 目录一、缓存问题1.1 缓存穿透1.1.1 问题来源1.1.2 解决方案1.2 缓存击穿1.2.1

vue解决子组件样式覆盖问题scoped deep

《vue解决子组件样式覆盖问题scopeddeep》文章主要介绍了在Vue项目中处理全局样式和局部样式的方法,包括使用scoped属性和深度选择器(/deep/)来覆盖子组件的样式,作者建议所有组件... 目录前言scoped分析deep分析使用总结所有组件必须加scoped父组件覆盖子组件使用deep前言

解决Cron定时任务中Pytest脚本无法发送邮件的问题

《解决Cron定时任务中Pytest脚本无法发送邮件的问题》文章探讨解决在Cron定时任务中运行Pytest脚本时邮件发送失败的问题,先优化环境变量,再检查Pytest邮件配置,接着配置文件确保SMT... 目录引言1. 环境变量优化:确保Cron任务可以正确执行解决方案:1.1. 创建一个脚本1.2. 修