Java并发:从超卖问题到锁的升级过程

假如我们现在有一百个线程,商品A库存量为100,售出方法为sale()

在没有上锁是,即时我们设置当库存量为零时停止售卖,但是也极有可能出现超卖的情况,这是由于我们售卖的方法没有原子性,在售出的过程中,库存为零时,其他线程可能刚好调用方法,这时条件没有更改,所以是无法及时停止的。

synchronized关键字

        使sale()方法一次最多服务一个线程,这样就解决了超卖的问题,此时涉及到锁升级过程

初始状态,线程A发过来请求,请求获取锁,此时sale()的对象锁处于空闲状态,获取成功,对象锁的对象头部分包含markword,用于记录当前获取锁的线程,此时为偏向锁,获取成功之后执行sql语句。

        线程A此时还在使用 sale()方法,也就是仍然占有这个锁,此时线程B过来了,也想要执行这个方法,那也需要获取这个锁,此时线程B将自己的线程ID与markword中记录的id进行对比,发现不同,那么锁升级为轻量级锁,线程B在旁边不断地CAS自旋尝试获取锁。

CAS不断地自旋其实是很消耗资源的,当线程B多次CAS仍然无法获取到锁的话,此时锁升级为重量级锁,线程B进入阻塞队列沉睡,等待唤醒。

        此时,如果其他线程想要尝试获取锁,竞争失败都会进入阻塞队列进行沉睡。只有当A执行完,释放锁,此时阻塞队列中的线程被全部唤醒,竞争成功的获取锁进而执行,其他竞争线程失败的继续沉睡,等待下一轮的唤醒。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值