java并发学习8:问题引入

1、小故事
  • 老王(操作系统)有一个功能强大的算盘(CPU),现在想把它租出去,赚一点外快

  • 小南、小女(线程)来使用这个算盘来进行一些计算,并按照时间给老王支付费用

  • 但小南不能一天24小时使用算盘,他经常要小憩一会(sleep),又或是去吃饭上厕所(阻塞 io 操作),有时还需要一根烟,没烟时思路全无(wait)这些情况统称为(阻塞)

  • 在这些时候,算盘没利用起来(不能收钱了),老王觉得有点不划算

  • 另外,小女也想用用算盘,如果总是小南占着算盘,让小女觉得不公平

  • 于是,老王灵机一动,想了个办法 [ 让他们每人用一会,轮流使用算盘

  • 这样,当小南阻塞的时候,算盘可以分给小女使用,不会浪费,反之亦然

  • 最近执行的计算比较复杂,需要存储一些中间结果,而学生们的脑容量(工作内存)不够,所以老王申请了一个笔记本(主存),把一些中间结果先记在本上

  • 计算流程是这样的

在这里插入图片描述

  • 但是由于分时系统,有一天还是发生了事故

  • 小南刚读取了初始值 0 做了个 +1 运算,还没来得及写回结果

  • 老王说 [ 小南,你的时间到了,该别人了,记住结果走吧 ],于是小南念叨着 [ 结果是1,结果是1…] 不甘心地到一边待着去了(上下文切换)

  • 老王说 [ 小女,该你了 ],小女看到了笔记本上还写着 0 做了一个 -1 运算,将结果 -1 写入笔记本

  • 这时小女的时间也用完了,老王又叫醒了小南:[小南,把你上次的题目算完吧],小南将他脑海中的结果 1 写入了笔记本

在这里插入图片描述

  • 小南和小女都觉得自己没做错,但笔记本里的结果是 1 而不是 0
2、问题分析

对于i++而言(i 为静态变量),实际会产生如下的 JVM 字节码指令:

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

而对应i–也是类似:

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

自减需要在主存和工作内存中进行数据交换:
在这里插入图片描述

在这里插入图片描述

3、临界区
  • 一个程序运行多个线程本身是没有问题的,问题出在多个线程访问共享资源

    * 多个线程读共享资源其实也没有问题
    * 在多个线程对共享资源读写操作时发生指令交错,就会出现问题
    
  • 一段代码块内如果存在对共享资源的多线程读写操作,称这段代码块为临界区

static int counter = 0;
static void increment() 
    // 临界区
{    counter++;}
static void decrement() 
    // 临界区
{    counter--;}

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值