假如我们现在有一百个线程,商品A库存量为100,售出方法为sale()
在没有上锁是,即时我们设置当库存量为零时停止售卖,但是也极有可能出现超卖的情况,这是由于我们售卖的方法没有原子性,在售出的过程中,库存为零时,其他线程可能刚好调用方法,这时条件没有更改,所以是无法及时停止的。
synchronized关键字
使sale()方法一次最多服务一个线程,这样就解决了超卖的问题,此时涉及到锁升级过程
初始状态,线程A发过来请求,请求获取锁,此时sale()的对象锁处于空闲状态,获取成功,对象锁的对象头部分包含markword,用于记录当前获取锁的线程,此时为偏向锁,获取成功之后执行sql语句。
线程A此时还在使用 sale()方法,也就是仍然占有这个锁,此时线程B过来了,也想要执行这个方法,那也需要获取这个锁,此时线程B将自己的线程ID与markword中记录的id进行对比,发现不同,那么锁升级为轻量级锁,线程B在旁边不断地CAS自旋尝试获取锁。
CAS不断地自旋其实是很消耗资源的,当线程B多次CAS仍然无法获取到锁的话,此时锁升级为重量级锁,线程B进入阻塞队列沉睡,等待唤醒。
此时,如果其他线程想要尝试获取锁,竞争失败都会进入阻塞队列进行沉睡。只有当A执行完,释放锁,此时阻塞队列中的线程被全部唤醒,竞争成功的获取锁进而执行,其他竞争线程失败的继续沉睡,等待下一轮的唤醒。