为了账号安全,请及时绑定邮箱和手机立即绑定

居然还有比 ReadWriteLock 更强的锁:StampedLock

标签:
Java JavaScript

原文来自于:https://zha-ge.cn/java/70

居然还有比 ReadWriteLock 更强的锁:StampedLock

有一天,手上维护的服务开始神秘性卡顿,大家掰着手指头数着是不是垃圾回收、数据库慢、线程池爆炸。结果扒着线程 dump 仔细一看,主线程正一脸懵逼地挂在了 ReadWriteLock 上。老哥,这玩意儿不是号称并发读写神器么?咋还成了绊脚石?

看着代码里那段熟悉的套路:

lock.readLock().lock();
try {
    // 一些业务逻辑
} finally {
    lock.readLock().unlock();
}

说实话,这种模式真是用了八百回。可是,问题就卡在这里:读多写少的局面下,依然有些线程等得脖子快长断了。就如排队买奶茶,好家伙,等了半天队伍没动,后面的人都快打起来了!

谁是强化锁 StampedLock?

正郁闷呢,隔壁“懂王”同事轻飘飘来了一句:“StampedLock不用试试?”我一愣,这啥玩意儿,听名字像是邮票一样粘在锁头上,能寄快递还是咋的?

查了查文档,发现 StampedLock 其实算是 Java 8 新加的黑科技。它号称支持“三段变形”:

  • 悄咪咪读:乐观读锁 tryOptimisticRead
  • 传统读锁:悲观读锁 readLock
  • 写操作:写锁 writeLock

牛逼吧?仿佛攒了三种超能力在一起。最关键,这玩意竟然还能避免读锁之间的阻塞,而且是靠“邮票”(stamp)来标识自己拿到的锁,时间戳都搬出来了。这要给 ReadWriteLock 打几分?起码星星多三颗吧。

踩坑瞬间

其实刚一看 StampedLock 的用法,那叫一个心跳加速。尤其是乐观读锁,看了官方 demo,满脑袋问号:

long stamp = lock.tryOptimisticRead();
int value = data;
if (!lock.validate(stamp)) {
    stamp = lock.readLock();
    try {
        value = data;
    } finally {
        lock.unlockRead(stamp);
    }
}

第一次用,我可开心了,写完就上生产(真不怕打死)。结果线上直接给我来了个“值读乱了”。隔壁业务同学都来找我聊天了,说“怎么你们缓存突然全是旧数据造的吗?”

原因其实简单粗暴——乐观读锁就是乐观,有写并发时 stamp 会失效,你得乖乖回到读锁再重新读一遍。可我一开始偷懒,validate 失败居然没管它还继续用脏数据……直接翻车。

后来又遇到个操作,unlock 忘了加 stamp,愣给 unlock 死在源码崖底下,找了十分钟才发现 unlockRead 需要传 stamp,这和 ReadWriteLock 可不一样,它不像 unlock() 那么好用。

经验启示

过来人的血泪经验如下总结,欢迎围观甚至拍砖:

  • 乐观读?用,但别懒。validate stamp 失败,记得老老实实重来一遍,别想着“应该没事吧”。
  • 写锁期间,所有乐观读都会被标记失效,所以对一致性要求真的高的时候,你得选悲观读。
  • “邮票”这东西,千万别乱搞。每个加锁方法返回的 stamp 必须匹配 unlock,否则有你好果汁喝。
  • 组合锁可玩性高,但不要随便组合,否则到时候 Deadlock 啦啦队直接喊进你家门。

StampedLock 给我带来的体感是:

优点 坑点/注意事项
提升读性能 乐观锁需二次校验
API 灵活 unlock 得要 stamp 参数
支持写转读等骚操作 出错时 bug 难排查

最后一个想吐槽点:StampedLock 其实是不可重入的(你 lock 两次会把自己锁死),而且还不支持条件变量,有点反人类。用之前三思,别拿正经业务现场试刀。

好啦,今天的邮票锁故事说完了——Java 永远有你不熟的小秘密,还得自己多踩踩坑头发才掉得够快。不说了,下次再聊,那会儿估计又冒出个什么“宇宙锁”了。

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号

举报

0/150
提交
取消