连载中 12/21

读写锁:读多写少的专属答案,与 StampedLock 乐观读

2026-10-28 · 38 阅读 · 0 评论 · 0 赞

独占锁的浪费

缓存、配置、路由表——典型的读多写少。synchronized 和 ReentrantLock 一视同仁:读和读也要互斥,可明明都是只读操作,本可以并行。读写锁补上这块短板,规则三条:写写互斥、读写互斥、读读共享——只有写是排他的。

ReentrantReadWriteLock 骨架

ReentrantReadWriteLock rw = new ReentrantReadWriteLock();

rw.readLock().lock();      // 读操作:共享,读读并行
try { /* 读缓存 */ } finally { rw.readLock().unlock(); }

rw.writeLock().lock();     // 写操作:独占,连读也挡
try { /* 更新缓存 */ } finally { rw.writeLock().unlock(); }

内核还是 AQS:state 一拆二,高 16 位记读锁、低 16 位记写锁——第 9 篇埋的伏笔在这兑现。支持重入;还支持锁降级:持有写锁时可以再拿读锁,然后放掉写锁,降级成只读——保证自己刚写的数据能立即可见地读回来。反方向读升级写不被支持:两个读线程同时想升级,各自等对方先放读锁,直接死锁,所以 API 干脆禁止。

它的两个软肋

其一,读锁挡写锁:读请求持续涌入时写线程可能一直排不上号,写被饿死(公平模式能缓解,吞吐下降)。其二,读读共享不是免费的:每次拿读锁、放读锁都是对 state 高 16 位的 CAS 操作,读多到极致时这部分开销反而成了瓶颈。于是有了更激进的方案。

StampedLock:乐观读的降维打击

写少到几乎不写的场景,连「拿读锁」都嫌贵。StampedLock 的乐观读:先不加锁,读一版数据,读完拿版本戳校验——期间没人写过就直接用;写过,转悲观读锁重读。绝大多数校验会通过,读路径近乎无锁:

StampedLock sl = new StampedLock();

double read() {
    long stamp = sl.tryOptimisticRead();   // 不加锁,只拿个版本戳
    double x = this.x, y = this.y;         // 先读到局部变量
    if (!sl.validate(stamp)) {             // 校验:期间发生过写吗?
        stamp = sl.readLock();             // 有——转悲观读锁重读
        try { x = this.x; y = this.y; }
        finally { sl.unlockRead(stamp); }
    }
    return x + y;
}

使用须知三条:乐观读读到的值必须先复制进局部变量再校验,别用着用着又被改;StampedLock 不可重入,同一线程重复获取会直接死锁;不支持 Condition。约束多,但读多写极少且写得极快时,它是最快的读写方案。

锁的故事到这里讲完。但有一类数据不走「共享」路线——每个线程想要自己独享的一份。下一篇 ThreadLocal:每个线程的抽屉,以及它那桩著名的内存泄漏。

☕
503

10 年全栈工程师 · 503咖啡馆主理人

#Java#读写锁#StampedLock#AQS#JUC

评论 (0)

热门推荐

连载中 11/22

主从搭建实操:从零配出一主两从

光讲原理不过瘾?手把手搭一主两从:my.cnf 六个参数、复制账号、GTID、CHANGE REPLICATION SOURCE TO、SHOW REPLICA STATUS 验收,附翻车排查清单。

#MySQL#主从复制#GTID#主从搭建#高可用
2026-05-07 · 10113 阅读 · 0 评论 · 0 赞
连载中 16/22

连接池:HikariCP 参数与连接风暴

连接池不是越大越好:8 核机器配 1000 连接反而更慢的数学原理,HikariCP 四个必调参数,maxLifetime 与 wait_timeout 的隐形陷阱。

#MySQL#连接池#HikariCP#maxLifetime#连接风暴
2026-05-10 · 9876 阅读 · 0 评论 · 0 赞
连载中 4/16

缓存穿透:恶意 ID 打穿 MySQL 的四道防线

请求的数据在缓存和数据库里都不存在时,缓存形同虚设。聊聊参数校验、空值缓存、布隆过滤器、限流熔断四道防线的原理与组合打法。

#Redis#缓存穿透#布隆过滤器#高可用
2026-05-16 · 9306 阅读 · 21 评论 · 287 赞