侧边栏壁纸
  • 累计撰写 72 篇文章
  • 累计创建 31 个标签
  • 累计收到 5 条评论

目 录CONTENT

文章目录

「Java同步原理与底层实现解析」-Peak-Gao

PeakGao
2024-11-27 / 0 评论 / 0 点赞 / 2 阅读 / 0 字 / 正在检测是否收录...
温馨提示:
部分素材可能会来自网络,若不小心影响到您的利益,请联系我们删除。
  • 原理概要:

java虚拟机中的同步基于进入与结束Monitor对象实现,无论是显式同步(同步代码块进入在jvm是根据monitorenter标志、结束是monitorexit标志,那最后一个是monitorexit是异常结束时被执行的释放指令)、隐式同步(同步方法无需通过字节码控制,而是ACC_SYNCHRONIZED声明为同步方法在jvm内部包装一个监视器锁被调用)都是如此,

  • 底层原理:(可重入的实现)

每一个锁关联一个线程持有者和一个计数器、当计数器为0时表示该锁没有被任何线程持有,此时任何线程都可以获得该锁并调用,当有一个线程请求成功时,jvm会记录下持有锁的线程并将计数器设为1,此时其他线程请求该锁,则必须等待,当持有该锁的线程再次请求这个锁,重入后将计数器加1,当线程退出该锁,计数器就会递减,如果计数器为0时则释放锁

同步代码块字节码

3 monitorenter
//...........
71 monitorexit
//...........
78 monitorexit
//...........
82 return        

同步方法字节码

在这里插入图片描述

  • 应用范围
  1. 可以保证在同一时刻,只有一个线程在访问被锁修饰的代码,也可以保证线程的变化,被另一个线程看到(可见性)
  2. 是一个互斥(所以有阻塞)、重量级锁
  3. 可以阻止jvm的指令重排序
  4. 总之使用同步会系统的很大开销、甚至可能会死锁
  • 应用方式:
  1. 修饰代码块:作用的对象是整个代码块的对象 FQA:当有一个线程访问这个代码块时,其他线程试图访问会出现阻塞 – |
  2. 方法:作用的对象是调用这个方法的对象 FQA:多线程下阻塞和修饰代码块等价,都锁定整个方法的内容 – |
  3. 静态方法:作用的对象是这个类的所有对象 FQA:多个对象也是一把锁,所以线程同步
  4. 类:作用主的对象是这个类的所有对象 FQA:多个对象也是一把锁,所以线程同步
  • 锁的状态:

1.无锁、
2.偏向锁、
3.轻量锁、
4.重量锁,
随着锁的竞争、从偏向锁到轻量级、在到重量级。锁的的升级是单向,也就是只能从低到高升级不会出现锁的降级

  • synchronized 的用法

a. synchronized 修饰 static静态方法 —— 锁住的是class对象
b.synchronized 修饰 普通方法 —— 锁住的是实例对象 (this)
c.synchronized (obj) 修饰代码块 —— 锁住的是obj对象

锁的状态记录在jvm对象头中

synchronized:他是对于当前虚拟机而言,但是同一个应用部署到多台服务器,它的实例是运行在多个不同的jvm中的之间是相互独立的,所以在多台服务器之间加锁需要用到分布式锁分布式锁:(redis实现,并不是实际意义上的加锁,只是setx一个key,每次去获取这个key(获取锁),释放这个key(释放锁))在使用分布式锁是会出现,在释放锁的时候如果前面的业务出问题了,导致释放锁没有执行,所以要对之前的业务逻辑进行异常捕获,并且将释放锁放到finally中,但是还会出现锁超时问题,将释放锁放到finally中就一定会被执行?在java中Exception是可以捕获的,但是机房停电、kill -9等操作,导致整个逻辑还没执行到finally就会出现问题,所以这个时候可以在setx之后设置一个过期时间,即使kill -9等操作,也会在这个过期时间将锁释放,这样的话后期的线程还是可以获取到锁的,

0
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin

评论区