
文章插图
4.2.4 通过synchronized关键字对代码块加锁private static void secKillGoodsByLock() throws SQLException {synchronized (lockObj) {secKillGoods();}}以上程序在进入秒杀方法时,都会通过synchronized关键字加锁,再次运行程序,我们发现不会出现负库存了

文章插图
但是如果在多进程或者分布式环境中,synchronized关键字会失效,让我们再启动一个进程,两个进程同时启动100000个线程进行秒杀(ps:同时启动十万个线程差点让我的电脑没缓过来…),终于出现了负库存的现象

文章插图
4.2.5 Redis锁
private static void secKillGoodsByRedisLock(){String id="1";String key="lock"+id;JedisUtil jedisUtil=new JedisUtil();String lockId=jedisUtil.getLock(key,5);if(null!=lockId){try{List list= DButil.query("select id,name,qty from t_goods where id=1 and qty>0");if(list!=null && list.size()>0){Object[] insertObject={lockId,new Date(),"nova7",Thread.currentThread().getName()};DButil.excuteDML("update t_goods set qty=qty-1 where id=1 ");DButil.excuteDML("insert into t_order values(?,?,?,?);",insertObject);System.out.println(Thread.currentThread().getName()+">>>抢到了."+lockId);jedisUtil.unLock(key,lockId);}else {System.out.println("抢完了");}} catch (SQLException e) {jedisUtil.unLock(key,lockId);e.printStackTrace();}}}以上代码只有在获取到Redis锁成功后,才会去执行扣库存和下单的逻辑,重复和上一步一样,两个进程同时启动100000个线程进行秒杀,看看结果
文章插图

文章插图
以上结果没有出现负库存的现象,显然是扛住了“秒杀”,getLock 的实现如下所示,其原理就是利用Redis setnx的原子性操作来控制并发,以下示例还设置了锁失效的时间,避免死锁 。当然还有许多的问题需要在实际应用场景中考虑,如在锁失效时间到了,秒杀动作未完成如何处理,Redis服务器崩溃了怎么办等等 。
public String getLock(String key,int timeout){Jedis jedis=null;try {jedis=getJedis();String value=https://www.isolves.com/it/cxkf/bk/2022-05-06/getId();long end=System.currentTimeMillis()+timeout;while (System.currentTimeMillis()>>>>获取锁成功 。");return value;}//当 key 存在但没有设置剩余生存时间时if(jedis.ttl(key)==-1){//设置失效时间jedis.expire(key,timeout);}}} catch (Exception e) {e.printStackTrace();}finally {if(null!=jedis){jedis.close();}}return null;} 参考文献:为什么需要锁,锁分类,锁粒度
各种锁以及使用场景
推荐阅读
- Docker私有仓库Registry删除镜像的方法
- 滇红茶有黑色的,红茶的泡多长时间
- 崂山红茶泡茶时间,崂山红茶的保质期
- 泡红茶的茶具名称,金骏茶的功效与作用
- 蜜糖泡红茶,蜜糖红茶
- 红茶泡蜂蜜的功效,红茶是否可以加蜂蜜
- 祁门红茶泡后,祁门红茶有什么好处
- 红茶种子是怎么样的,祁红红茶怎么泡
- 很细的红茶叶,藏红花枸杞茶的泡法
- 杜仲和红茶怎么泡,杜仲肉苁蓉茶的功效与作用
