关于这个问题,我要说一下我之前做过的一个关于售卖商品的项目.
第一次我只给售卖商品这个界面写了一个判断商品库存是否大于零,大于零时库存减一,等于零时返回一个商品告罄.然后在测试时发现商品数量只剩一个时会出现被多个用户购买的情况.于是我Debug了一下发现是多线程问题,然后我就加了一把同步锁.但是又出现了另一个问题,当用户量增多时服务器压力就会增大,然后我就换成了Redis同步锁.
在redis同步锁时我用的是里面的setNX 他的特性是当一个线程进入时会设置一个键并返回true并上锁,当另一个线程进来时会返回一个false,并阻止她进入,这样会出现一个问题,当服务器因为一些意外问题关闭会导致第一个线程的键一直留在里面并上锁,然后后面的线程就会无法进入而堵塞出现死锁的情况.这样就要加上一个过期时间,这样就会解决服务器意外关闭出现死锁的问题.
但是当设置过期时间过短时就会出现时间到了自动解锁而第二个线程进来时第一个线程仍在处理,当第一个线程处理完时发现他自己的锁已经被释放,于是转而去释放第二个线程的锁.这样又会导致第三个线程进入.长时间就会出现刚开始的超卖问题.
在处理第一个时间问题时我是这样处理的,先创建一个子线程,每5秒确认主线程是否在线,当主线程在线时就将过期时间重置来解决过期时间过短的问题
第二个问题就需要给锁加一个唯一Id让每个线程根据这个唯一Id释放自己的锁这样就不会出现线程乱释放锁的问题
当然redis分布式锁是有一定局限性,如果需要多机部署就需要用到 Redisson 来实现了