<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Xsync on Zampo Blog</title><link>https://blog.cpdd.fyi/tags/xsync/</link><description>Recent content in Xsync on Zampo Blog</description><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Mon, 13 Jul 2026 14:30:00 +0800</lastBuildDate><atom:link href="https://blog.cpdd.fyi/tags/xsync/index.xml" rel="self" type="application/rss+xml"/><item><title>你以为 sync.Map 无锁？它的锁藏在三个地方</title><link>https://blog.cpdd.fyi/posts/go-sync-map-mechanism/</link><pubDate>Mon, 13 Jul 2026 14:30:00 +0800</pubDate><guid>https://blog.cpdd.fyi/posts/go-sync-map-mechanism/</guid><description>&lt;p&gt;这套对话，我在 code review 里见过很多次。&lt;/p&gt;
&lt;p&gt;A 说：这个 map 读多写少，并发安全得处理一下。
B 说：那把 map + RWMutex 换成 sync.Map 吧，无锁的，更快。&lt;/p&gt;
&lt;p&gt;第一句不完全错，第二句基本错了。&lt;/p&gt;
&lt;p&gt;sync.Map 不是无锁 map。它内部有一把 Mutex，还有一套 read / dirty 双 map 的调度逻辑。它只是努力让你常见的读路径不走锁，但写、删除、miss、dirty 提升这些路径一个都绕不开锁。&lt;/p&gt;
&lt;p&gt;你选 &lt;code&gt;sync.Map&lt;/code&gt;，不是因为它在所有场景下都更快，而是因为你的 workload 正好落在它设计的那条窄路径上。&lt;/p&gt;
&lt;p&gt;但绝大多数人跳过这个前提。&lt;/p&gt;
&lt;h2 id="read-和-dirty一把锁两个桶"&gt;read 和 dirty：一把锁两个桶&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;sync.Map&lt;/code&gt; 的内部结构（Go 1.25.4）可以浓缩成五样东西：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Map&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;mu&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Mutex&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;read&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;atomic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Pointer&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;readOnly&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// 无锁读的主流路径&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;dirty&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;any&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// 写和 miss 的后备路径&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;misses&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// 读 miss 计数&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;其中 &lt;code&gt;readOnly&lt;/code&gt; 又包了一层：&lt;/p&gt;</description></item></channel></rss>