一、超卖现象
举例1:
产生原因图解解决办法1
解决办法1的代码实现代码: 超卖现象举例2
产生原因图解解决方法
方法1:1方法2: 加锁 synchronized 解决方法2
方法3: 加锁 reentrantlock(并发包里的锁,可重入锁)
一、超卖现象 举例1:某商品库存数量10件,结果卖出了15件。
商品的卖出数量超出了库存数量,这肯定不行。
产生原因
首先有3张表,order,order_item,product
product表的字段:
product表的数据:
order表的字段:
order_item表的字段:
在多线程并发的情况下,会产生超卖现象。
利用方法1,不在程序中扣减库存,解决问题。
这个方法还不能解决问题,同时下5个单,商品会变成负数。
超卖现象举例2商品变成负数
产生原因并发监测库存,造成库存充足的假象。
update更新库存,导致库存变成负数。
可以先使用最简单的方法,在更新商品数量后,再校验商品的库存,如果是负数,抛出异常。
方法2: 加锁 synchronized在校验库存和扣减库存统一加锁,使之成为原子性操作,并发的时候,只有获取到锁的线程才能校验扣减库存。
在扣减库存结束后释放锁,确保库存不会变成负数。
可以使用synchronized关键字解决超卖问题,这是最原始的锁哦。
- 如果在创建订单的方法上加synchronized关键字,这样能够解决问题吗?
答案是不能的,因为锁住的是当前方法,但是事务没有被锁住,线程1的锁释放后,线程2进入该方法,事务可能还没提交,这就导致了查询库存的时候,还是原来的库存。
- 那么如何控制事务呢?
这个时候就要手动的控制事务
首选注入平台事务管理器
注入事务定义
在方法的前面创建事务
在方法的最后提交事务
解决方法2在异常的地方进行事务的回滚
利用synchronized块 解决问题 。
和方法1类似,就不多说了,在synchronized块中可以是对象,也可以是类,this代表的是当前类的对象,要保证是单例的。
然后在并发的地方加上lock.lock();,在事务提交之后加上lock.unlock();
还要把要并发的地方加上try,catch,finally,在finally里加上lock.unlock(); ,防止锁没有被释放。



