深入理解Java并发编程之共享模型内存

概述

本章主要深入学习共享变量在多线程间的【可见性】问题与多条指令执行时的【有序性】问题。

1.Java内存模型

JMM即Java Memory Model,它定义了主存、工作内存抽象概念底层对应着CPU寄存器、缓存、硬件内存、CPU指令优化等。

JMM体现在以下几个方面

  • 原子性-保证指令不会受到线程上下文切换的影响

  • 可见性-保证指令不会受cpu缓存的影响

  • 有序性-保证指令不会受cpu指令并行优化的影响

  1. 可见性

退不出的循环

先来看一个现象,main线程对run变量的修改对于t线程不可见,导致了t线程无法停止:

分析:1.初始状态,t线程刚开始从内存读取了run的值到工作内存

2.因为t线程要频繁从主内存中读取run的值,JIT编译器会将run的值缓存至自己工作内存中的高速缓存中,减少对主存中run 的访问,提高效率

3.1秒之后,main线程修改了run的值,并同步至主存,而t是从自己工作内存中的高速缓存中读取这个变量的值,结果永远是旧值

解决方法

volatile(易变关键字)

它可以用来修饰成员变量和静态成员变量,他可以避免线程从自己的工作缓存中查找变量的值,必须到主存中获取它的值,线程操作volatile变量都是直接操作主存

可见性与原子性

前面例子体现的实际就是可见性,它保证的是在多个线程之间,一个线程对 volatile变量的修改对另一个线程可见,不能保证原子性,仅用在一个写线程,多个读线程的情况︰上例从字节码理解是这样的:

比较一下之前我们将线程安全时举的例子∶两个线程一个i++一个i--,只能保证看到最新值,不能解决指令交错

5.3有序性

排序导致结果有问题

  • 情况1︰线程1先执行,这时ready = false ,所以进入else分支结果为1

  • 情况2∶线程2先执行num= 2,但没来得及执行ready= true,线程1执行,还是进入 else分支,结果为1

  • 情况3∶线程2执行到 ready = true,线程1执行,这回进入if分支,结果为4(因为num已经执行过了)

  • 情况4:线程2执行ready= true,切换到线程1,进入if分支,相加为О,再切回线程2执行num= 2,结果为0

这种现象叫做指令重排,是JIT编译器在运行时的一些优化,这个现象需要通过大量测试才能复现:

解决方法

volatile修饰的变量,可以禁用指令重排

volatile原理

happens-before

happens-before规定了对共享变量的写操作对其它线程的读操作可见,它是可见性与有序性的一套规则总结,抛开以下 happens-before 规则,JMM并不能保证一个线程对共享变量的写,对于其它线程对该共享变量的读可见

  • 线程解锁m之前对变量的写,对于接下来对m加锁的其它线程对该变量的读可见

  • 线程对volatile的写,对接下来其他线程对该变量的读可见

  • 线程start前对变量的写,对该线程开始后对该变量的读可见

  • 线程结束前对变量的写,对其它线程得知它结束后的读可见(比如其它线程调用t1.isAlive()或t1.join()等待它结束)

  • 线程 t1 打断 t2(interrupt)前对变量的写,对于其他线程得知 t2 被打断后对变量的读可见(通过t2.interrupted 或 t2.isInterrupted)

  • 对变量默认值(0,false,null)的写,对其它线程对该变量的读可见

  • 具有传递性,如果x hb-> y 并且y hb-> z 那么有x hb-> z ,配合 volatile 的防指令重排,有下面的例子

4.第五章小结

  • 可见性-由JVM缓存优化引起

  • 有序性-由JVM指令重排序优化引起

  • happens-before规则

  • 原理方面

  • CPU指令并行

  • volatile

  • 模式方面

  • 两阶段终止模式的volatile改进

  • 同步模式之balking

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值