第二章 java并发机制的底层实现原理

发布时间:2023年12月29日

序言

java 代码在编译后会变成java字节码,字节码被类加载器加载到jvm里,jvm执行字节码,最终需要转化为汇编指令在cpu上执行,java中所使用的并发机制依赖于jvm的实现和cpu的指令,本章我们将深入底层一起探索java并发机制的底层实现原理

volatile的应用

volatile 是轻量级的synchronized,它在多处理器开发中保证了共享变量的可见性和有序性,可见性的意思是当一个线程修改一个共享变量时,另外一个线程能读到这个修改的值,它比synchronized执行成本更低,没有上下文切换与调度

  • 共享变量可见性实现原理
    使用缓存锁,对进行操作缓存进行锁定,操作完之后,再写到内存,这是其他处理器的缓存会变为无效,下次访问内存,会重新读取最新的值
  • 共享变量有序性
    在 JVM 底层 volatile 是采用“内存屏障”来实现的。带有volatile关键字时,会多出一个lock前缀指令,lock前缀指令实际上相当于一个内存屏障,来实现指令有序性(这个后面章节会详细讲解

synchronized的实现原理与应用

synchronized在并发编程中,应该说是元老级人物,很多人也称呼它为重量级锁,但在java1.6中进行了优化,引入偏向锁、轻量级锁

  • 底层原理
    monitorenter 指令是在编译后插入到同步代码块的开始位置,而monitorexit是插入到方法结束和异常处,jvm要保证每个monitorenter必须有对应的monitorexit与之配对,任何对象都有一个monitor关联,当且一个monitor被持有后,它将处于锁定状态,线程执行到monitorenter指令是,将会尝试获取对象锁对应monitor的所有权,即尝试获取锁。

  • java对象头
    synchronized用的锁是存在java对象头里面,对象头里面的Mark word 存储对象的hashcode 、分代年龄和锁标记位
    在这里插入图片描述

  • 锁的升级

大多数情况,锁不仅不存在多线程竞争,总是由同一个线程获取,这时获得锁就是偏向锁。
如果遇到线程的竞争,偏向锁就会释放,变为轻量级锁,当出现有自旋,长时间获取不到,就变为重量级锁

原子操作的实现与原理

java 是通过CAS方式实现原子操作
CAS:就是循环比较期望值与旧值,是否相等,相等则进行替换,不相等就一直循环尝试替换。

  • 注意

ABA问题:在cas方式操作值的时候,有可能出现,线程A与线程B,线程A对变量i=100进行修改200,再修改为100,那么线程B再修改A时发现,还是原来100,就会进行修改,这时就会出现了ABA问题
案例:假设你有存款1000元,你去银行转账500,转账成功了,但不小心又点一次次转账的之前,有人给你转了500,因为发现存款是1000,没有扣500,所以第二次误点转账也会成功(可能此案例不符合生活场景)。
为了解决这问题,每次转账都加一个版本号来区分是否原来的金额。

文章来源:https://blog.csdn.net/GZ946/article/details/135285006
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。