yamlln

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

synchronized

synchronized

1、定义:

synchronized:是一种互斥锁,一次只能允许一个线程进入被锁住的代码块;

2、场景:

(1)修饰实例方法,对应锁是对象实例

(2)修饰对象方法,对应锁是当前类的class实例

(3)修饰代码块,对应锁是传入synchronized的对象实例

3、原理:

从反编译来看:

修饰方法时,编译器会生成ACC_SYNCHRONIZED关键字来标识;

修饰代码块时,会依赖 monitorenter 和 monitorexit 指令

前置知识:

不管是修饰什么,对应的锁都是一个对象;在内存中,对象又分为三部分:对象头,对象实际数据、对齐填充;

其中我们需要重点关注对象头中的 MarkWord 的信息,他会记录对象关于锁的信息;每个对象会存在一个与之对应的monitor对象,monitor中存储着当前持有锁的线程和等待锁的线程队列

Mark Word对锁的状态记录一共有4种:无锁、偏向锁、轻量级锁和重量级锁

无锁

偏向锁:Jvm认为只有某个线程会执行同步代码,MarkWord会直接记录线程的id;只要线程进来,就会对比线程id,如果相等则获取得到锁,执行同步代码;如果id不同,则用CAS尝试修改线程id,如果修改成功,则可以获取得到锁,执行同步代码;如果修改失败,则说明有竞争环境,撤销偏向锁,升级为轻量锁;

轻量级锁:线程会在栈帧下创建LockRecord,并拷贝MarkWord信息,有一个onwer指针指向加锁的对象;当线程执行到同步代码,尝试用CAS将MarkWord指向到线程栈帧的LockRecord,如果成功,则获取轻量锁;如果失败,则自旋(重试),自旋一定程度后,升级到重量级锁;

重量级锁:monitor对象会存储当前进入线程的id,设置MarkWord的monitor地址,将阻塞的线程存储在monitor的等待线程队列中;他加锁依赖操作系统的mutex指令,需要用户态和内核态切换,性能损耗十分明显;(JDK 1.6之前是重量级锁)

引入了偏向锁和轻量级锁,就是为了在不同的使用场景使用不同的锁,进而提高效率。锁只有升级,没有降级

不同锁场景:

(1)只有一个线程进入临界区,使用偏向锁;

(2)多个线程交替进入临界区,使用轻量级锁;

(3)多个线程同时进入临界区,使用重量级锁;

posted on   yamlln  阅读(198)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示