分布式锁
分布式锁锁
还记得我们学习多线程那会有一个经典的防止超卖的案例吗?双十一商家举行了一场空前的活动,很多商品都参加了秒杀,其中有一个商品只有5件库存,如果让你模拟一场对这个商品的秒杀活动,你会怎么编写程序呢?很多人可能已经胸有成足地想好了,相信有不少人是这样写的。
首先编写商品类 public class Good{ Integer count=5; /** * 卖出一件商品,模拟一次用户点击和请求 */ public void sale(){ if(count>0){ this.count-=1; System.out.println("卖出一件商品,剩余:"+count); } } public Integer getCount() { return count; } }
再来启动多个线程来模拟秒杀 Good good = new Good(); while (good.getCount()>0){ new Thread(()->{ good.sale(); }).start(); } System.out.println("抢购结束");
好了,如果此时点击运行,理想中打印的结果是这样的 卖出一件商品,剩余:4 卖出一件商品,剩余:3 卖出一件商品,剩余:2 卖出一件商品,剩余:1 卖出一件商品,剩余:0 抢购结束
可实际上大概率并不是理想中的结果,而是类似这样的 卖出一件商品,剩余:4 卖出一件商品,剩余:3 卖出一件商品,剩余:1 卖出一件商品,剩余:2 卖出一件商品,剩余:4 卖出一件商品,剩余:4 卖出一件商品,剩余:4 卖出一件商品,剩余:-2 卖出一件商品,剩余:-5 卖出一件商品,剩余:-4 抢购结束 卖出一件商品,剩余:-2
怎么解决这个问题,防止出现超卖和类似问题呢?相信大家已经懂了,那便是今天的主角:锁。 Lock和synchronized
在单体流行的时代,对于解决上面的问题,最容易想到的有两种解决方案: Lock ReentrantLock lock = new ReentrantLock(); Good good = new Good(); while (good.getCount()>0){ new Thread(()->{ lock.lock(); good.sale(); lock.unlock(); }).start(); } System.out.println("抢购结束"); synchronized Object lock = new Object(); Good good = new Good(); while (good.getCount()>0){ new Thread(()->{ synchronized(lock){ good.sale(); } }).start(); } System.out.println("抢购结束");
本文的重点是分布式锁,故不再详细讲解Lock和synchronized的用法,感兴趣的同学可以自行进行学习。 分布式锁
微服务越来越流行,上面的两种方式在微服务中已经变的不再适用,试想一下,某服务运行在3台服务器上,第一个请求在A服务器上获得了锁,此时第二个请求进入B服务器,此时它仍然可以获得锁。为了解决Lock和synchronized的局限性,分布式锁便派上用场了。
分布式锁有不同的觉得方案,有用ZooKeeper实现有,有基于ETCD实现的,也有基于Redis实现的,具体采用什么方案,需要综合具体场景以及当前已经使用的技术栈来决定,本文以Redis为例来讲述通用的案例。 基于spring boot starer的实现
Spring Boot 实现 Redis 分布式锁在 spring-integration 这个项目中,所以需要这三个依赖: org.springframework.boot spring-boot-starter-data-redis org.springframework.boot spring-boot-starter-integration org.springframework.integration spring-integration-redis
配置 @Bean(destroyMethod = "destroy") public RedisLockRegistry redisLockRegistry(RedisConnectionFactory redisConnectionFactory) { return new RedisLockRegistry(redisConnectionFactory, "lock"); }
示例 @Autowired RedisLockRegistry redisLockRegistry; @Test public void test(){ Good good = new Good(); while (good.getCount()>0){ new Thread(()->{ Lock obtain = redisLockRegistry.obtain("lock-key"); try { boolean b = obtain.tryLock(10, TimeUnit.SECONDS); if(success){ good.sale(); } } catch (InterruptedException e) { e.printStackTrace(); obtain.unlock(); }finally { obtain.unlock(); } }).start(); } System.out.println("抢购结束"); } 基于Redisson的实现 Good good = new Good(); while (good.getCount()>0){ new Thread(()->{ Lock obtain = redisLockClient.getLock("key"); try { boolean success = obtain.tryLock(10, TimeUnit.SECONDS); if(success){ good.sale(); } } catch (InterruptedException e) { obtain.unlock(); }finally { obtain.unlock(); } }).start(); } System.out.println("抢购结束");
当然,本案例只是讲解分布式锁的使用方法,并不一定完全切合所有的使用场景,例如上诉案例中关于库存量,实际场景中便不能直接存储在内存中,而是使用redis等进行存储
更多Java学习资料关注我免费领取
HarmonyOS(鸿蒙系统)加持下荣耀(Play4)又推送更新上线OS随着华为国产系统(鸿蒙OS)的研发成功推送上线,华为的国产OS分布式操作系统,真正的实现了万物互联的应用场景。笔者自从用华为品牌的手机以来,华为上线推送(鸿蒙OS)后,就更新了这款
马上三月份,即将发布的几款手机,华为荣耀苹果均有新品2月份的发布会热潮结束了,什么红米K50电竞版oppofindX5等等,但是上半年的新机还没有结束,接下来还有更令人激动的华为荣耀苹果等发布会,我们一起来看看都有哪些手机吧。第一款
华为隐藏大招!全新麒麟5G芯片出现,两款两千档廉价新机齐发虽然遭到了史无前例的打压导致华为不保昔日的国产手机一哥地位,但很明显华为并不想在今年碌碌无为,还是希望能够继续维持运转,坚持到拨开云雾见青天的那一天。这段时间国产厂商纷纷发布新机,
教你19种关闭小米手机广告方法本内容来源于什么值得买APP,观点仅代表作者本人作者薄荷有点凉其实哪个安卓手机品牌多少都有广告投放,只是形式不同而已,关键是如何关掉广告。由于这两年一直用小米手机,手机安装好需要的
8个压箱底的宝藏App,实用又强大,手机秒变黑科技突然想问大家一个问题,你们的手机上都有哪些好用的App?今天我就来推荐8个压箱底的宝藏App,实用又强大,让你的手机秒变黑科技。01秒启动特色1秒启动手机应用。现在的很多App启动
vivox20手机可以用几年?如果是从寿命上来讲,应该是属于因人而异的事情,都能看到不少爱护的好的人的手机,用个四五年的都大有人在,还有些爱护不好的,基本上几个月就歇菜,当然,这也取决于手机厂商的用料质量问题,
在美国硅谷工作的码农,有什么工作上的烦恼?估计大家都认为在硅谷做软件工程师是非常幸福的事情,拿着令人艳羡的高薪享受着各种各样的免费福利,不过这些福利的背后要付出的努力却是大家不知道的。那些令人艳羡的高薪和福利作为世界科技之
面对智能手表的独立化课题,手机厂商走出了四种路线新年伊始,苹果放出了一则广告片。公路海洋农场,镜头从高空俯视,缓慢推进,并依次切换。广袤而平坦的地面,被渲染了一层阴暗的色调,一直延伸到天际。广告片时长一分钟,但直到结束,画面中都
百度屏蔽了中国裁判文书网,这事没那么简单近日,在百度身上发生了一件匪夷所思的事儿。2月21日上午,有人在百度搜索中国裁判文书网相关词条,搜索结果显示,没有找到与中国裁判文书网相关的网页,而搜狗必应等搜索引擎均可正常搜索。
聊两个最具潜力的板块昨天聊了三个大家关心的板块,今天说说当下最具投资潜力的板块!我说的机会是什么机会呢?是那种足以实现财富自由,实现你下一代财富,人生自由的板块!1,芯片半导体!不论电动汽车,光伏新能
AirPods怎么选?入手前这些细节须知悉可以看到,去牛秋季不仅全新发布了AirPods3,苹果还悄悄的将AirPodsPro的充电盒更新为了MagSafe充电盒,支持磁吸充电。这样对比三款耳机的区别,你就会发现相比前代,