<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>RWMutex on Zampo Blog</title><link>https://blog.cpdd.fyi/tags/rwmutex/</link><description>Recent content in RWMutex on Zampo Blog</description><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Thu, 02 Jul 2026 17:08:53 +0800</lastBuildDate><atom:link href="https://blog.cpdd.fyi/tags/rwmutex/index.xml" rel="self" type="application/rss+xml"/><item><title>线上锁竞争别急着换 RWMutex：Go 同步原语背后的三笔账</title><link>https://blog.cpdd.fyi/posts/go-sync-primitives-locks-pool/</link><pubDate>Thu, 02 Jul 2026 17:08:53 +0800</pubDate><guid>https://blog.cpdd.fyi/posts/go-sync-primitives-locks-pool/</guid><description>&lt;p&gt;接口 p99 突然抖起来，pprof 里 mutex wait 很显眼。&lt;/p&gt;
&lt;p&gt;会议上最容易出现的三个动作是：锁太粗，换成 &lt;code&gt;RWMutex&lt;/code&gt;；分配太多，把 buffer 放进 &lt;code&gt;sync.Pool&lt;/code&gt;；再不行，把临界区附近的代码拆一拆。&lt;/p&gt;
&lt;p&gt;听起来都像优化。&lt;/p&gt;
&lt;p&gt;但这三个动作也都可能把问题带偏。Mutex 不只是“排队拿锁”；RWMutex 不是“读多写少就快”；sync.Pool 更不是一个稳定保存对象的池子。它们背后真正做的，是吞吐、尾延迟、公平性和 GC 压力之间的交易。&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.cpdd.fyi/images/go-sync-primitives-locks-pool/cover.svg" alt="Go 同步原语三笔账"&gt;&lt;/p&gt;
&lt;p&gt;如果你不知道这笔交易是什么，线上排查时看到的每个指标都会变成直觉题。&lt;/p&gt;
&lt;p&gt;这篇只压一个判断：Go 的同步原语不是性能按钮，而是调度和内存可见性的契约。你不是在选“哪个更快”，你是在选“愿意把哪种代价暴露给系统”。&lt;/p&gt;
&lt;p&gt;这个判断听起来有点绕，但落到代码里很具体：锁竞争要看临界区，读写锁要看读路径是否真能并行，Pool 要看分配和 GC 压力是否真的下降。&lt;/p&gt;
&lt;h2 id="mutex-不是绝对公平它默认先保吞吐"&gt;Mutex 不是绝对公平，它默认先保吞吐&lt;/h2&gt;
&lt;p&gt;刚接触 Mutex 时很容易以为它就是排队，一个一个拿锁。&lt;/p&gt;
&lt;p&gt;Go 的 Mutex 没这么简单。&lt;/p&gt;
&lt;p&gt;Go 1.25.4 的源码注释把 Mutex 分成两种模式：正常模式和饥饿模式。正常模式下，等待者确实按 FIFO 排队，但被唤醒的 goroutine 并不直接拥有锁。它还要和刚来的 goroutine 一起抢。&lt;/p&gt;
&lt;p&gt;刚来的 goroutine 已经在 CPU 上跑着，天然占便宜。被唤醒的等待者可能输，输多了就回到队头继续等。&lt;/p&gt;
&lt;p&gt;这不是 bug，这是取舍。&lt;/p&gt;
&lt;p&gt;正常模式吞吐更好。源码注释也写得很直：normal mode has considerably better performance。一个 goroutine 可以连续多次抢到锁，减少交接成本。&lt;/p&gt;
&lt;p&gt;代价是尾延迟。&lt;/p&gt;
&lt;p&gt;如果某个等待者超过约 1ms 还没拿到锁，Mutex 会尝试切到 starvation mode。饥饿模式下，解锁的 goroutine 直接把所有权交给队首等待者；新来的 goroutine 不抢锁，也不自旋，只能排队。&lt;/p&gt;</description></item></channel></rss>