游戏电视苹果数码历史美丽
投稿投诉
美丽时装
彩妆资讯
历史明星
乐活安卓
数码常识
驾车健康
苹果问答
网络发型
电视车载
室内电影
游戏科学
音乐整形

一种比读写锁更快的锁,还不赶紧认识一下

  摘要:一起来聊聊在高并发环境下比ReadWriteLock更快的锁StampedLock。
  本文分享自华为云社区《【高并发】高并发场景下一种比读写锁更快的锁,看完我彻底折服了!!(建议收藏)云社区华为云》,作者:冰河。什么是StampedLock?
  ReadWriteLock锁允许多个线程同时读取共享变量,但是在读取共享变量的时候,不允许另外的线程多共享变量进行写操作,更多的适合于读多写少的环境中。那么,在读多写少的环境中,有没有一种比ReadWriteLock更快的锁呢?
  答案当然是有!那就是我们今天要介绍的主角JDK1。8中新增的StampedLock!没错,就是它!
  StampedLock与ReadWriteLock相比,在读的过程中也允许后面的一个线程获取写锁对共享变量进行写操作,为了避免读取的数据不一致,使用StampedLock读取共享变量时,需要对共享变量进行是否有写入的检验操作,并且这种读是一种乐观读。
  总之,StampedLock是一种在读取共享变量的过程中,允许后面的一个线程获取写锁对共享变量进行写操作,使用乐观读避免数据不一致的问题,并且在读多写少的高并发环境下,比ReadWriteLock更快的一种锁。StampedLock三种锁模式
  这里,我们可以简单对比下StampedLock与ReadWriteLock,ReadWriteLock支持两种锁模式:一种是读锁,另一种是写锁,并且ReadWriteLock允许多个线程同时读共享变量,在读时,不允许写,在写时,不允许读,读和写是互斥的,所以,ReadWriteLock中的读锁,更多的是指悲观读锁。
  StampedLock支持三种锁模式:写锁、读锁(这里的读锁指的是悲观读锁)和乐观读(很多资料和书籍写的是乐观读锁,这里我个人觉得更准确的是乐观读,为啥呢?我们继续往下看啊)。其中,写锁和读锁与ReadWriteLock中的语义类似,允许多个线程同时获取读锁,但是只允许一个线程获取写锁,写锁和读锁也是互斥的。
  另一个与ReadWriteLock不同的地方在于:StampedLock在获取读锁或者写锁成功后,都会返回一个Long类型的变量,之后在释放锁时,需要传入这个Long类型的变量。例如,下面的伪代码所示的逻辑演示了StampedLock如何获取锁和释放锁。publicclassStampedLockDemo{创建StampedLock锁对象publicStampedLockstampedLocknewStampedLock();获取、释放读锁publicvoidtestGetAndReleaseReadLock(){longstampstampedLock。readLock();try{执行获取读锁后的业务逻辑}finally{释放锁stampedLock。unlockRead(stamp);}}获取、释放写锁publicvoidtestGetAndReleaseWriteLock(){longstampstampedLock。writeLock();try{执行获取写锁后的业务逻辑。}finally{释放锁stampedLock。unlockWrite(stamp);}}}
  StampedLock支持乐观读,这是它比ReadWriteLock性能要好的关键所在。ReadWriteLock在读取共享变量时,所有对共享变量的写操作都会被阻塞。而StampedLock提供的乐观读,在多个线程读取共享变量时,允许一个线程对共享变量进行写操作。
  我们再来看一下JDK官方给出的StampedLock示例,如下所示。classPoint{privatedoublex,y;privatefinalStampedLockslnewStampedLock();voidmove(doubledeltaX,doubledeltaY){anexclusivelylockedmethodlongstampsl。writeLock();try{xdeltaX;ydeltaY;}finally{sl。unlockWrite(stamp);}}doubledistanceFromOrigin(){Areadonlymethodlongstampsl。tryOptimisticRead();doublecurrentXx,currentYy;if(!sl。validate(stamp)){stampsl。readLock();try{currentXx;currentYy;}finally{sl。unlockRead(stamp);}}returnMath。sqrt(currentXcurrentXcurrentYcurrentY);}voidmoveIfAtOrigin(doublenewX,doublenewY){upgradeCouldinsteadstartwithoptimistic,notreadmodelongstampsl。readLock();try{while(x0。0y0。0){longwssl。tryConvertToWriteLock(stamp);if(ws!0L){stampws;xnewX;ynewY;break;}else{sl。unlockRead(stamp);stampsl。writeLock();}}}finally{sl。unlock(stamp);}}}
  在上述代码中,如果在执行乐观读操作时,另外的线程对共享变量进行了写操作,则会把乐观读升级为悲观读锁,如下代码片段所示。doubledistanceFromOrigin(){Areadonlymethod乐观读longstampsl。tryOptimisticRead();doublecurrentXx,currentYy;判断是否有线程对变量进行了写操作如果有线程对共享变量进行了写操作则sl。validate(stamp)会返回falseif(!sl。validate(stamp)){将乐观读升级为悲观读锁stampsl。readLock();try{currentXx;currentYy;}finally{释放悲观锁sl。unlockRead(stamp);}}returnMath。sqrt(currentXcurrentXcurrentYcurrentY);}
  这种将乐观读升级为悲观读锁的方式相比一直使用乐观读的方式更加合理,如果不升级为悲观读锁,则程序会在一个循环中反复执行乐观读操作,直到乐观读操作期间没有线程执行写操作,而在循环中不断的执行乐观读会消耗大量的CPU资源,升级为悲观读锁是更加合理的一种方式。StampedLock实现思想
  StampedLock内部是基于CLH锁实现的,CLH是一种自旋锁,能够保证没有饥饿现象的发生,并且能够保证FIFO(先进先出)的服务顺序。
  在CLH中,锁维护一个等待线程队列,所有申请锁,但是没有成功的线程都会存入这个队列中,每一个节点代表一个线程,保存一个标记位(locked),用于判断当前线程是否已经释放锁,当locked标记位为true时,表示获取到锁,当locked标记位为false时,表示成功释放了锁。
  当一个线程试图获得锁时,取得等待队列的尾部节点作为其前序节点,并使用类似如下代码判断前序节点是否已经成功释放锁:while(pred。locked){省略操作}
  只要前序节点(pred)没有释放锁,则表示当前线程还不能继续执行,因此会自旋等待;反之,如果前序线程已经释放锁,则当前线程可以继续执行。
  释放锁时,也遵循这个逻辑,线程会将自身节点的locked位置标记为false,后续等待的线程就能继续执行了,也就是已经释放了锁。
  StampedLock的实现思想总体来说,还是比较简单的,这里就不展开讲了。StampedLock的注意事项
  在读多写少的高并发环境下,StampedLock的性能确实不错,但是它不能够完全取代ReadWriteLock。在使用的时候,也需要特别注意以下几个方面。StampedLock不支持重入
  没错,StampedLock是不支持重入的,也就是说,在使用StampedLock时,不能嵌套使用,这点在使用时要特别注意。StampedLock不支持条件变量
  第二个需要注意的是就是StampedLock不支持条件变量,无论是读锁还是写锁,都不支持条件变量。StampedLock使用不当会导致CPU飙升
  这点也是最重要的一点,在使用时需要特别注意:如果某个线程阻塞在StampedLock的readLock()或者writeLock()方法上时,此时调用阻塞线程的interrupt()方法中断线程,会导致CPU飙升到100。例如,下面的代码所示。publicvoidtestStampedLock()throwsException{finalStampedLocklocknewStampedLock();Threadthread01newThread((){获取写锁lock。writeLock();永远阻塞在此处,不释放写锁LockSupport。park();});thread01。start();保证thread01获取写锁Thread。sleep(100);Threadthread02newThread(()阻塞在悲观读锁lock。readLock());thread02。start();保证T2阻塞在读锁Thread。sleep(100);中断线程thread02会导致线程thread02所在CPU飙升thread02。interrupt();thread02。join();}
  运行上面的程序,会导致thread02线程所在的CPU飙升到100。
  这里,有很多小伙伴不太明白为啥LockSupport。park();会导致thread01会永远阻塞。这里,冰河为你画了一张线程的生命周期图,如下所示。
  这下明白了吧?在线程的生命周期中,有几个重要的状态需要说明一下。NEW:初始状态,线程被构建,但是还没有调用start()方法。RUNNABLE:可运行状态,可运行状态可以包括:运行中状态和就绪状态。BLOCKED:阻塞状态,处于这个状态的线程需要等待其他线程释放锁或者等待进入synchronized。WAITING:表示等待状态,处于该状态的线程需要等待其他线程对其进行通知或中断等操作,进而进入下一个状态。TIMEWAITING:超时等待状态。可以在一定的时间自行返回。TERMINATED:终止状态,当前线程执行完毕。
  看完这个线程的生命周期图,知道为啥调用LockSupport。park();会使thread02阻塞了吧?
  所以,在使用StampedLock时,一定要注意避免线程所在的CPU飙升的问题。那如何避免呢?
  那就是使用StampedLock的readLock()方法或者读锁和使用writeLock()方法获取写锁时,一定不要调用线程的中断方法来中断线程,如果不可避免的要中断线程的话,一定要用StampedLock的readLockInterruptibly()方法获取可中断的读锁和使用StampedLock的writeLockInterruptibly()方法获取可中断的悲观写锁。
  最后,对于StampedLock的使用,JDK官方给出的StampedLock示例本身就是一个最佳实践了,小伙伴们可以多看看JDK官方给出的StampedLock示例,多多体会下StampedLock的使用方式和背后原理与核心思想。
  点击下方,第一时间了解华为云新鲜技术
  华为云博客大数据博客AI博客云计算博客开发者中心华为云

谷歌安卓版App将引入新功能,用户可删除最近15分钟搜索历史3月21日消息,谷歌证实,谷歌安卓版App引入一个新功能,允许用户删除最近15分钟的搜索历史。谷歌发言人内德阿德里安斯(NedAdriance)在声明中表示:我们目前正在……谷歌总部的安卓机器人雕像没了IT之家3月20日消息,谷歌的安卓雕像曾经占据的谷歌总部的一角,现在那里已经变成了一块泥地。一些参观了谷歌44号楼的人声称,安卓标志性的机器人雕像已经神秘消失了。根据An……小米11TProRedmiNote11Pro新手机用户可免费IT之家2月18日消息,据Neowin报道,小米公司宣布,购买小米新设备之一的用户将能够获得最多三个月的YouTubePremium订阅。作为与谷歌YouTube合作的一部分,……谷歌安卓13将进一步限制侧载App权限IT之家5月4日消息,据AndroidPolice报道,Android的无障碍服务旨在为残障用户提供帮助,但这套工具非常强大,以至于其他应用程序经常使用它来启用引人注目的功能。……三星星回购服务上线一年前原价9699元的S21Ultra能卖感谢IT之家网友斗皇圣佛的线索投递!IT之家5月22日消息,日前,三星官翻机官微宣布,星回购服务首发上线,可以高于市场行情20的价格回收符合标准的三星手机。官方表示……提前申请手机商标?vivo已申请X100至X1000感谢IT之家网友华南吴彦祖的线索投递!IT之家5月12日消息,信息显示,近期,维沃移动通信有限公司申请注册VIVOX200、VIVOX300、VIVOX500至VIVOX……谷歌确认Pixel7Pro秋季面世标志性摄像头模组设计,搭载IT之家5月12日消息,在今天凌晨举行的谷歌2022IO开发者大会上,谷歌推出了一系列硬件产品,其中有一些是以预告的形式公布,并非正式发布,谷歌新一代旗舰机型Pixel7系列便……谷歌禁止俄罗斯从GooglePlay商店下载或更新付费安卓AIT之家5月10日消息,据Neowin报道,早在3月份,由于许多公司撤出俄罗斯,支付系统中断,谷歌宣布将暂停其在俄罗斯的GooglePlay计费系统。当时,它要求开发人员免费提……谷歌开发者大会剧透硬件新品大爆发,Android13成配角北京时间5月10日消息,美国东部时间5月11日13点(北京时间5月12日1点),谷歌公司的2022年度开发者大会GoogleIO将拉开帷幕。在本届大会上,硬件新品有可能会唱主角……混干皮秋冬护肤攻略混干皮肤有什么特点?混干性肤质一般都是在脸部的T区、下唇下方、鼻翼两侧易出油,两颊皮肤偏干。皮肤毛孔较小,有一些细纹,脸部没有光泽。混干皮秋冬季易出现的问题踏……Pixel6a即将发布,消息称谷歌有望重返印度手机市场IT之家5月9日消息,在过去的几个月里,谷歌的新机Pixel6a已经被爆料者们曝光的差不多了,泄露的渲染图和规格描述了对谷歌即将推出的Pixel6a的期待。与去年的Pix……测试发现索尼Xperia1IV发热时120Hz刷新率会降至6IT之家5月12日消息,昨日,索尼正式发布了全新旗舰手机Xperia1IV,该搭载了骁龙8Gen1处理器,采用6。5英寸4KAMOLED显示屏,支持120Hz刷新率,售价为14……
国家邮政局预计前三季度快递业务收入超2019年全年水平中新社北京10月8日电(记者刘育英)中国国家邮政局8日发布的报告称,前三季度,预计快递业务量和业务收入同比增速分别约为4。2和3。5,业务收入超2019年全年水平。这份《……麒麟湾公园两处冒水,水流过的地方草木枯黄,咋回事儿?近日,微友太阳雨致电本报热线反映,麒麟湾公园环境优美,深受市民喜爱,可是最近她在公园游玩时发现,公园南端龙头景观附近不断有清水冒出,清水流过的地方小草都枯死了,树也成了光杆,很……神舟十三号载人飞船10月16日凌晨发射回顾神舟飞船精彩升空瞬2021年10月16日,经空间站阶段飞行任务总指挥部研究决定,神舟十三号载人飞船将于10月16日凌晨发射,发射时间瞄准北京时间16日0时23分。飞行乘组由航天员翟志刚、王亚平和……越南队又夺冠了,他们如何不到20年就从鱼腩队称雄东南亚看更多精彩足球文章,请关注作者头条号!对于中国球迷来讲,2022年第一个惊雷就是大年初一男足国家队1比3败给越南,而且输得灰头土脸,60年不败越南的记录止于今朝。也让人们……阿曼将于2024年发射第一颗深空纳米卫星据muscatdaily1月26日报道,在阿曼运输、通信和信息技术部的主持下,国际新兴技术公司(ETCO)与创新的太空公司维珍轨道(VirginOrbit)、SatRevolu……越吃越香的几道家常菜,色香味俱全,做法简单【干煸豆角土豆】主料土豆:2个,豆角:250辅料油:适量,盐:适量,蒜:适量,宴友食用油、干辣椒:适量,葱:适量,味精:适量具体步骤1。土豆……月销破4万的小孩贴嘴神器真的有用吗?儿科专家这样说孩子睡觉老是打鼾?孩子睡觉张着嘴,甚至有了腺样体面容的特征?最近,不少家长在出现这样的困扰后,将目光投向睡觉粘嘴胶带、小孩贴嘴神器上。在孩子入睡前,将这类胶带贴在嘴上,以……青岛和东京有多少相似之处?青岛和东京:有多少相似之处?青岛和东京有着相似的地形,两个城市都拥有深入腹地的港湾。这些港湾的一边通常是一个小型半岛,而另一边则是一片山地。这样的地理条件为两……吐血整理!谁说国产免费软件不好用,这五款软件太良心了谁说国产免费软件不好用!别总说只有外国佬设计的好用,吐血整理了这五款神仙国产软件,知乎超多人推荐!目录:1、佐糖Picwish2、简道云3、Vizard录屏软件4、幕布5、小丸……十位明星再扮成名角色带货,一波情怀牌打出,你的钱包还捂得住吗现在很多明星在不拍戏的时候都会选择带货,毕竟流量为王的时代,他们拥有庞大的粉丝群体,不变现确实可惜了。老戏骨也好,隐退好多年的过气明星也罢,都借着这一股东风,出来搞直播带……小米再度引领行业,MIUI13隐私安全再度升级,网友最安全的MIUI13已经开始了推送,我一直选择小米手机有个原因就是因为MIUI的隐私防护和信息安全功能,MIUI确实是开创了手机隐私保护的诸多功能。比如MIUI12。5推出的各项……不可轻视数据中心高能耗问题想象一下,如果一种先进设备每年要浪费上千亿千瓦时电,你会认为大量采购该设备是一种高质量的投资吗?这种情况在数字经济的热潮中并不鲜见。在全国各地新一轮数字新基建,以及东数西算国家……
友情链接:易事利快生活快传网聚热点七猫云快好知快百科中准网快好找文好找中准网快软网