分布式锁的实现方式( 二 )

分布式锁的实现方式
文章插图
 
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;}参考文献:
为什么需要锁,锁分类,锁粒度
各种锁以及使用场景




推荐阅读