面经连接池 - 线程原理(一)JMM(Java内存模型) 篇

如果要理解多线程问题首先要了解多线程是如何工作的

主内存与工作内存:

线程,工作内存,主内存三者交互关系图:

主内存:可以线程共享的变量(会出现竞争关系) 包括实例字段 静态字段 数组对象的元素(此处与Java中还有所不同)(不包括局部变量与方法参数)变量必须在主内存中产生

工作内存:该线程使用到的变量的主内存副本拷贝,线程对变量的所有操作(读取赋值)都必须在工作内存中进行,不能直接读取主内存中的变量,不同的线程间也无法直接访问对方工作内存中的变量,线程间变量值的传递都需要通过主内存来完成

注:JMM 与 JVM 中堆栈二者是没有关系;如果二者要强硬对上,那么主内存主要对应着Java堆与方法区,工作内存对应着虚拟机栈部分 虚拟机甚至可能会让工作内存优先存储于寄存器和高速缓存中。


内存间交互操作:

一个变量如何从主内存拷贝到工作内存中、以及工作内存如何同步到主内存中,Java内存模型中定义了 8 种操作来完成的,虚拟机实现每一种操作都是原子的,不可分割的。(当线程对变量进行了操作这 6 步都必须按序执行完成 不一定连续 如果未加锁的话 可能会不同线程的不同操作交叉执行

1.read (读取):作用于主内存的变量,将一个变量的值从主内存传输到工作内存中

2.load(载入):作用于工作内存的变量,将read操作得到的变量的值放入工作内存的变量副本中

3.use(使用):作用于工作内存的变量,把工作内存中的变量交给执行引擎处理 虚拟机遇到使用变量会处理

4.assign(赋值):作用于工作内存的变量,把执行引擎收到的值赋给工作变量,虚拟机遇到赋值操作会执行

5.store(存储):作用于工作内存的变量,将工作内存中变量的值传给主内存

6.read(写入):作用于主内存中的变量,将工作内存中变量的值放入主内存中

如果有加锁操作还会执行下面两步:(多次执行 lock 操作 必须要执行相同次数的 unlock 才会解锁 不允许对未lock的变量unlock  也不允许去unlock一个被其他线程锁住的变量)如同 锁 与 钥匙 的关系 一把钥匙 只能开一把锁不能开其他锁

1.lock(锁定):作用于主内存的变量,将一个变量标识为一条线程独占(且会清空工作变量的值,重新执行)

2.unlock(解锁):作用于主内存的变量,将锁定状态的变量释放出来,才可继续被其他线程使用


特别解析:volatile 型变量特殊规则

1.此变量对所有线程具有可见性(可以认为不存在不一致的情况 但是并发下线程不安全的):当一个线程修改了该变量的值,都必须同步回主内存,这个新得到的值对于所有线程都是可以立即知道的(所有线程要使用该变量的值 都必须先从主内存刷新到最新的值) 而普通变量则做不到

2.禁止指令重排优化

首先为什么会指令重排呢?

各个变量内存中存储并不是连续的(只是为了便于研究将内存中的区域划分为一整块一整块的)为了使运算器的处理单元尽可能的充分利用,处理器可能会对输入的代码进行乱序执行优化,但保证执行结果和未进行优化的结果是一致的

拓展:Java内存模型要求如上 8 个操作必须具有原子性,不可分割。但允许将没有被 volatile 修饰的 64 的数据类型(double,float)读写操作分两步进行 也就是有可能读到 "半个变量"的值 但在虚拟机层面上又将读写操作实现成了原子操作 --(故可以不考虑这方面的影响)


Java内存模型并发操作需要实现的三个特征:

原子性:Java内存模型来直接保证原子性变量的操作包括 read、load、assign、store 和 write ;Java的基本类型读写操作可认为是具有原子性的

如果我们想要从更大范围而不仅仅是从单个变变量考虑时,Java 为我们提供了 lock 和 unlock 操作 尽管虚拟机未向用户直接开放,但是可以使用同步块 synchronized 关键字(底层反应的字节码指令是 monitorenter(翻译:进入监控 ? )monitorexit(翻译  :退出监控 ? ))

可见性:可见性是一个线程修改了共享变量的值,其他变量能够立即知道(除 volatile 以外还有 synchronizd 和 final )

   synchronizd 的可见性:“ 一个变量执行 unlock 操作之前必须先把此变量同步到主内存中 ”

   final 的可见性:一旦初始化,其他线程就可以通过 this 访问到 且是不可变的

有序性:如果在一个在线程内看所有操作都是有序的(线程表现为串行化)在更宏观来看,所有操作都是无序的(指令重排优化,工作内存和主内存变量的值同步延迟 );在Java中由 volatile 和 synchronized 两个关键字来保证线程之间操作的有序性

   volatile 的有序性:禁止指令重排优化

   synchronized的有序性:“一个变量在同一时刻只允许一条线程对其进行 lock 操作”

 

 

 

 

----   参考《深入理解Java虚拟机:JVM高级特性与最佳实践》   ---

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值