Synchronized

synchronized是什么

java关键字,是互斥锁,只允许一个线程进入被锁住的代码块
修饰实例方法时,锁是对象实例
修饰静态方法时,锁是类的class实例
修饰代码块时,锁是传入的对象

类对象实例和类class实例是两个锁,不冲突

synchronized原理

通过反编译(javap),当修饰方法时,编译器生成ACC_SYNCHRONIZED关键字来标识,当修饰代码块时,会在开头和结尾用monitorenter和monitorexit标识
以monitorenter为例,当线程执行到monitorenter时,就回去获取对象锁。对象锁由对象头的mark word和monitor对象组成,一个对象实例对应一个monitor对象,markword有指向monitor对象的指针,monitor对象存储着当前持有锁的线程以及等待锁的线程队列。如果锁计数器等于0,获取锁成功,计数器+1。如果失败,判断是否是当前线程持有锁,是,计数器+1,获取锁成功,否则获取锁失败

1.6之后做了什么优化

1.6前

synchronized是重量级锁,进入同步代码块时,monitor对象保存线程id,将monitor地址设置到对象的markword,将阻塞线程加入等待队列。它加锁依赖底层操作系统的Mutex相关指令实现,所以有用户态和内核态切换,性能损耗严重

1.6

引入偏向锁和轻量级锁,在Jvm层面实现加锁逻辑,不依赖底层操作系统,没有切换消耗
因此markword记录的锁状态有4种:无锁、偏向锁、轻量级锁、重量级锁
偏向锁:jvm认为没有竞争环境,直接在markword记录线程id,每次执行时比较线程id是否相等,相等就可以获取锁,执行同步代码;如果不相等,用CAS修改线程id,修改成功则获取锁;失败则说明有竞争,锁升级为轻量级锁。
轻量级锁:当前线程会在栈帧创建lockrecord,lockrecord拷贝markword信息,且有个owner指针指向锁对象。执行到同步代码时,用CAS尝试将markword指向线程的lockrecord,成功则获取到锁,失败则自旋,自旋一定次数后升级重量级锁。
重量级锁:线程执行到代码块,如果锁空闲则markword指向monitor记录线程id,monitor,如果锁被占了,再判断是否是当前占锁线程,是计数器+1,否则添加到等待队列;

对象头markword
synchronized锁的四种状态

参考:
Java6 及以上版本对 synchronized 的优化
Java 锁与线程的那些事 - 有赞技术团队

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值