<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>线程访问模型 on Dorkytiger 的小屋</title>
    <link>https://www.dorkytiger.top/c-plus-plus/c-plus-plus-concurrent-programming/04-thread-models/</link>
    <description>Recent content in 线程访问模型 on Dorkytiger 的小屋</description>
    <generator>Hugo</generator>
    <language>en-us</language>
    <atom:link href="https://www.dorkytiger.top/c-plus-plus/c-plus-plus-concurrent-programming/04-thread-models/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>SPSC (单写单读) 的极致优化</title>
      <link>https://www.dorkytiger.top/c-plus-plus/c-plus-plus-concurrent-programming/04-thread-models/01-spsc/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://www.dorkytiger.top/c-plus-plus/c-plus-plus-concurrent-programming/04-thread-models/01-spsc/</guid>
      <description>&lt;p&gt;SPSC（Single Producer Single Consumer）是并发队列的&lt;strong&gt;性能天花板&lt;/strong&gt;。因为只有一个线程写、一个线程读，我们&lt;strong&gt;完全不需要CAS&lt;/strong&gt;，只需要&lt;strong&gt;内存屏障&lt;/strong&gt;保证可见性，就能实现&lt;strong&gt;每秒数亿次&lt;/strong&gt;的数据交换。&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&#34;1-spsc-为什么可以零-cas&#34;&gt;1. SPSC 为什么可以零 CAS？&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;多生产者/多消费者 (MPMC): 需要CAS保证原子性
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ↓
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;单生产者/多消费者 (SPMC): 需要CAS保护生产者竞争
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ↓
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;多生产者/单消费者 (MPSC): 需要CAS保护消费者竞争
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ↓
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;单生产者/单消费者 (SPSC): 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - 写指针 (head)：只有生产者修改 → 不需要原子操作
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - 读指针 (tail)：只有消费者修改 → 不需要原子操作
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - 唯一需求：生产者写完数据后，消费者能看到 → 需要内存屏障
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;核心认知&lt;/strong&gt;：SPSC不需要任何原子RMW（Read-Modify-Write）指令，只需要：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;普通内存拷贝&lt;/strong&gt;（&lt;code&gt;memcpy&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Release屏障&lt;/strong&gt;（生产者写完数据后刷新Store Buffer）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Acquire屏障&lt;/strong&gt;（消费者读取数据前清空Invalidation Queue）&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h3 id=&#34;2-环形缓冲区ring-buffer-spsc的经典实现&#34;&gt;2. 环形缓冲区（Ring Buffer）—— SPSC的经典实现&lt;/h3&gt;
&lt;h3 id=&#34;数据结构&#34;&gt;数据结构&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;template&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;typename&lt;/span&gt; T, size_t Capacity&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;SPSCRingBuffer&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;static_assert&lt;/span&gt;((Capacity &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt; (Capacity &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;)) &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Capacity must be power of 2 for efficient modulo&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 缓存行对齐：避免伪共享
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;alignas&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;64&lt;/span&gt;) std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;atomic&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;size_t&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; head{&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;};  &lt;span style=&#34;color:#75715e&#34;&gt;// 生产者写位置 (消费者读)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;alignas&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;64&lt;/span&gt;) std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;atomic&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;size_t&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; tail{&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;};  &lt;span style=&#34;color:#75715e&#34;&gt;// 消费者读位置 (生产者写)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 数据存储：缓存行对齐，避免伪共享
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;alignas&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;64&lt;/span&gt;) T buffer[Capacity];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 生产者：写入数据
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; enqueue(&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; T&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt; item) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; size_t current_head &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; head.load(std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;memory_order_relaxed);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; size_t next_head &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; (current_head &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;) &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt; (Capacity &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// 检查队列是否已满
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (next_head &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; tail.load(std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;memory_order_acquire)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; false; &lt;span style=&#34;color:#75715e&#34;&gt;// 队列满
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// 写入数据 (普通内存拷贝)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        buffer[current_head] &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; item;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// Release屏障：确保数据写入完成，再更新head
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// 等价于: std::atomic_thread_fence(std::memory_order_release)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        head.store(next_head, std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;memory_order_release);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; true;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 消费者：读取数据
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;dequeue&lt;/span&gt;(T&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt; item) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; size_t current_tail &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; tail.load(std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;memory_order_relaxed);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// 检查队列是否为空
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (current_tail &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; head.load(std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;memory_order_acquire)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; false; &lt;span style=&#34;color:#75715e&#34;&gt;// 队列空
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// 读取数据 (普通内存拷贝)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        item &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; buffer[current_tail];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// Acquire屏障：确保数据读取前，tail更新已完成
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; size_t next_tail &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; (current_tail &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;) &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt; (Capacity &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        tail.store(next_tail, std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;memory_order_release);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; true;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;内存布局图示&#34;&gt;内存布局图示&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;环形缓冲区 (Capacity=8, 掩码=7):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+------------------------------------------------------------------+
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;| 索引: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |  (使用位运算 &amp;amp; 7 取模)    |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+------------------------------------------------------------------+
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      ↑                    ↑
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      |                    |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    tail (消费者)       head (生产者)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;生产者在 head 处写入，然后 head = (head+1) &amp;amp; 7
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;消费者在 tail 处读取，然后 tail = (tail+1) &amp;amp; 7
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;当 head == tail → 队列空
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;当 (head+1) &amp;amp; 7 == tail → 队列满 (留一个空位区分空和满)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h3 id=&#34;3-性能核武器批量处理batch-processing&#34;&gt;3. 性能核武器：批量处理（Batch Processing）&lt;/h3&gt;
&lt;p&gt;单元素入队/出队虽然快，但&lt;strong&gt;批量操作&lt;/strong&gt;能把吞吐量推向极致。&lt;/p&gt;</description>
    </item>
    <item>
      <title>MPSC (多写单读) 在异步系统中的落地</title>
      <link>https://www.dorkytiger.top/c-plus-plus/c-plus-plus-concurrent-programming/04-thread-models/02-mpsc/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://www.dorkytiger.top/c-plus-plus/c-plus-plus-concurrent-programming/04-thread-models/02-mpsc/</guid>
      <description>&lt;p&gt;这个问题直接触及&lt;strong&gt;异步系统设计的灵魂&lt;/strong&gt;！MPSC（Multi-Producer Single-Consumer）是&lt;strong&gt;日志系统、网络收包、数据库WAL&lt;/strong&gt;的黄金模型。我们的目标很明确：&lt;strong&gt;让成千上万个生产者疯狂提交任务，而单个消费者线程以内存带宽极限速度刷盘/处理。&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&#34;1-mpsc-的天然困境多写竞争&#34;&gt;1. MPSC 的天然困境：多写竞争&lt;/h3&gt;
&lt;p&gt;MPSC 的难点在于：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;多个生产者&lt;/strong&gt;争抢同一个队列 → 需要 CAS 保护。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;一个消费者&lt;/strong&gt;需要看到所有生产者的提交 → 需要全局可见性。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;如果直接用 &lt;code&gt;push&lt;/code&gt; + CAS 逐个入队&lt;/strong&gt;，在高并发下会产生&lt;strong&gt;缓存行乒乓&lt;/strong&gt;（所有生产者都在抢 &lt;code&gt;head&lt;/code&gt; 指针的缓存行），吞吐量断崖式下跌。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;解决方案&lt;/strong&gt;：&lt;strong&gt;批量提交（Batch Submission）&lt;/strong&gt; + &lt;strong&gt;本地缓冲（Thread-Local Buffer）&lt;/strong&gt;。&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&#34;2-mpsc-批量提交流程三阶段&#34;&gt;2. MPSC 批量提交流程（三阶段）&lt;/h3&gt;
&lt;h3 id=&#34;核心思想每个生产者先攒一批然后一次-cas-把整批交给消费者&#34;&gt;核心思想：&lt;strong&gt;每个生产者先攒一批，然后一次 CAS 把整批交给消费者。&lt;/strong&gt;&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[阶段1: 生产者本地缓冲]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    每个线程有自己的本地队列 (线程局部存储)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    任务先写入本地队列 (无竞争，极快)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[阶段2: CAS 批量提交]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    本地队列满了 (或超时) → 获取共享队列的全局锁（一次CAS）
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    把整批任务挂到共享队列尾部
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[阶段3: 消费者批量消费]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    消费者一次性取走所有任务 (使用内存屏障保证可见性)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    批量处理/刷盘 → 极高吞吐
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h3 id=&#34;3-工业级-mpsc-队列实现批处理--环形缓冲区&#34;&gt;3. 工业级 MPSC 队列实现（批处理 + 环形缓冲区）&lt;/h3&gt;
&lt;h4 id=&#34;数据结构设计&#34;&gt;数据结构设计&lt;/h4&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;template&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;typename&lt;/span&gt; T, size_t LocalBatchSize &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;256&lt;/span&gt;, size_t GlobalSize &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1024&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1024&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;MPSCBatchQueue&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// ============ 全局共享队列 (环形缓冲区) ============
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;GlobalQueue&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;alignas&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;64&lt;/span&gt;) std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;atomic&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;size_t&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; write_index{&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;};  &lt;span style=&#34;color:#75715e&#34;&gt;// 生产者CAS抢位置
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;alignas&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;64&lt;/span&gt;) std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;atomic&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;size_t&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; read_index{&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;};   &lt;span style=&#34;color:#75715e&#34;&gt;// 消费者读位置
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;alignas&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;64&lt;/span&gt;) T buffer[GlobalSize];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// 保证容量是2的幂，使用位运算取模
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;constexpr&lt;/span&gt; size_t MASK &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; GlobalSize &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;static_assert&lt;/span&gt;((GlobalSize &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt; (GlobalSize &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;)) &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;GlobalSize must be power of 2&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    GlobalQueue global_queue;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// ============ 生产者本地缓冲 (线程局部) ============
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;LocalBuffer&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        size_t count{&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        T items[LocalBatchSize];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 线程局部存储：每个生产者有自己的缓冲
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;thread_local&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; LocalBuffer local_buffer;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 生产者接口：提交单个任务
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;bool&lt;/span&gt; enqueue(&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; T&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt; item) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// 1. 写入本地缓冲 (无竞争，极快)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        local_buffer.items[local_buffer.count&lt;span style=&#34;color:#f92672&#34;&gt;++&lt;/span&gt;] &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; item;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// 2. 如果本地缓冲满了，批量提交到全局队列
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (local_buffer.count &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;=&lt;/span&gt; LocalBatchSize) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            flush_local_buffer();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; true;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 生产者接口：强制刷新（如程序退出前）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;flush&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        flush_local_buffer();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 消费者接口：批量获取任务
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Batch&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; T&lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; data;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        size_t count;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Batch &lt;span style=&#34;color:#a6e22e&#34;&gt;dequeue_batch&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; size_t current_read &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; global_queue.read_index.load(std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;memory_order_acquire);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; size_t current_write &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; global_queue.write_index.load(std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;memory_order_acquire);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        size_t available &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; current_write &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt; current_read;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (available &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; {&lt;span style=&#34;color:#66d9ef&#34;&gt;nullptr&lt;/span&gt;, &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;}; &lt;span style=&#34;color:#75715e&#34;&gt;// 队列空
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// 尽量一次性取出所有可用数据 (但不要超过环形缓冲区边界)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        size_t count &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;min(available, GlobalSize &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt; (current_read &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt; GlobalQueue&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;MASK));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; T&lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; data &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;global_queue.buffer[current_read &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt; GlobalQueue&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;MASK];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// 注意：这里不立即更新read_index，让消费者处理完再更新
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// (或者使用双指针技术，下面会讲)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; {data, count};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 消费者接口：提交消费进度 (批量标记已处理)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;commit_read&lt;/span&gt;(size_t count) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        size_t new_read &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; global_queue.read_index.load(std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;memory_order_relaxed) &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; count;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        global_queue.read_index.store(new_read, std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;memory_order_release);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 批量提交本地缓冲到全局队列
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; flush_local_buffer() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (local_buffer.count &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// 1. 用 CAS 抢占全局队列的写入位置 (唯一原子操作!)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        size_t start_index &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; global_queue.write_index.fetch_add(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            local_buffer.count, std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;memory_order_acquire);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// 2. 计算在环形缓冲区中的起始位置
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        size_t start_pos &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; start_index &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt; GlobalQueue&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;MASK;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        size_t end_pos &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; (start_index &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; local_buffer.count) &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt; GlobalQueue&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;MASK;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// 3. 复制数据到全局队列 (可能跨越环形边界)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (start_pos &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt; end_pos) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#75715e&#34;&gt;// 不跨越边界：直接拷贝
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            memcpy(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;global_queue.buffer[start_pos], 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                   local_buffer.items, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                   local_buffer.count &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;sizeof&lt;/span&gt;(T));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#75715e&#34;&gt;// 跨越边界：分两段拷贝
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            size_t first_part &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; GlobalSize &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt; start_pos;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            memcpy(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;global_queue.buffer[start_pos], 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                   local_buffer.items, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                   first_part &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;sizeof&lt;/span&gt;(T));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            memcpy(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;global_queue.buffer[&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;], 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                   &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;local_buffer.items[first_part], 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                   (local_buffer.count &lt;span style=&#34;color:#f92672&#34;&gt;-&lt;/span&gt; first_part) &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;sizeof&lt;/span&gt;(T));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// 4. 清空本地缓冲
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        local_buffer.count &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h3 id=&#34;4-性能关键消费者双指针技术&#34;&gt;4. 性能关键：消费者&amp;quot;双指针&amp;quot;技术&lt;/h3&gt;
&lt;p&gt;消费者如果每处理完一条就更新 &lt;code&gt;read_index&lt;/code&gt;，会产生大量缓存行写操作。&lt;strong&gt;优化的做法是：消费者批量处理，只更新一次 &lt;code&gt;read_index&lt;/code&gt;。&lt;/strong&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>SPMC (单写多读) 与 线程池任务分发（Work-Stealing）</title>
      <link>https://www.dorkytiger.top/c-plus-plus/c-plus-plus-concurrent-programming/04-thread-models/03-spmc-work-stealing/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://www.dorkytiger.top/c-plus-plus/c-plus-plus-concurrent-programming/04-thread-models/03-spmc-work-stealing/</guid>
      <description>&lt;h3 id=&#34;1-spmc单写多读的硬件本质&#34;&gt;1. SPMC（单写多读）的硬件本质&lt;/h3&gt;
&lt;h4 id=&#34;场景定义&#34;&gt;场景定义&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;1个写者（Writer）&lt;/strong&gt;：生产数据（如配置更新、日志聚合、时钟信号）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;N个读者（Reader）&lt;/strong&gt;：各自独立消费数据（如多个统计线程、监控面板、热备进程）。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;硬件挑战写者如何让所有读者看到最新数据&#34;&gt;硬件挑战：写者如何让所有读者看到最新数据？&lt;/h4&gt;
&lt;h5 id=&#34;方案a共享锁stdshared_mutex-读者间乒乓&#34;&gt;方案A：共享锁（&lt;code&gt;std::shared_mutex&lt;/code&gt;）—— 读者间乒乓&lt;/h5&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;shared_mutex mtx;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; shared_data;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;writer&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;unique_lock lock(mtx);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    shared_data &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; new_value; &lt;span style=&#34;color:#75715e&#34;&gt;// 独占锁 → 缓存行 E→M
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;reader&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;shared_lock lock(mtx);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; local &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; shared_data; &lt;span style=&#34;color:#75715e&#34;&gt;// 共享锁 → 缓存行 E→S
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;硬件代价&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;写者修改时，发 &lt;strong&gt;RFO（Read For Ownership）&lt;/strong&gt;，使所有读者的缓存行失效（&lt;code&gt;I&lt;/code&gt;状态）。&lt;/li&gt;
&lt;li&gt;读者读时，重新从主存/写者缓存加载（Cache Miss + 总线流量）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;缓存行在N+1个核心间频繁迁移&lt;/strong&gt;，延迟随读者数线性增加。&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 id=&#34;方案brcuread-copy-update-读者零开销&#34;&gt;方案B：RCU（Read-Copy-Update）—— 读者零开销&lt;/h5&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;atomic&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;*&amp;gt;&lt;/span&gt; global_ptr; &lt;span style=&#34;color:#75715e&#34;&gt;// 指向共享数据的指针
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;writer&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; old &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; global_ptr.load(std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;memory_order_acquire);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; new_data &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;old); &lt;span style=&#34;color:#75715e&#34;&gt;// 拷贝
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;new_data &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; new_value;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    global_ptr.store(new_data, std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;memory_order_release); &lt;span style=&#34;color:#75715e&#34;&gt;// 发布新指针
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 等待所有读者退出后，delete old (延迟回收)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;reader&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; data &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; global_ptr.load(std&lt;span style=&#34;color:#f92672&#34;&gt;::&lt;/span&gt;memory_order_acquire);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; local &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;data; &lt;span style=&#34;color:#75715e&#34;&gt;// 完全无锁，无原子操作（除了指针load）
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;硬件行为&lt;/strong&gt;：&lt;/p&gt;</description>
    </item>
    <item>
      <title>MPMC (多写多读) 与 工业级无锁队列（如 LMAX Disruptor）</title>
      <link>https://www.dorkytiger.top/c-plus-plus/c-plus-plus-concurrent-programming/04-thread-models/04-mpmc-disruptor/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://www.dorkytiger.top/c-plus-plus/c-plus-plus-concurrent-programming/04-thread-models/04-mpmc-disruptor/</guid>
      <description>&lt;p&gt;欢迎来到&lt;strong&gt;并发编程的“诸神之战”&lt;/strong&gt;——MPMC（Multi-Producer Multi-Consumer）。&lt;/p&gt;
&lt;p&gt;这是并发领域&lt;strong&gt;最难啃的骨头&lt;/strong&gt;，也是区分“普通程序员”和“系统架构师”的分水岭。你之前的 SPSC 是“单行道”，MPSC 是“多入口单出口”，而 MPMC 是**“多入口多出口的疯狂立交桥”**。&lt;/p&gt;
&lt;p&gt;要把 MPMC 写好，靠 CAS 硬刚是不行的，那会让 CPU 缓存行“炸裂”。我们需要引入工业级杀器：&lt;strong&gt;LMAX Disruptor&lt;/strong&gt;（无锁环形缓冲区）。&lt;/p&gt;
&lt;hr&gt;
&lt;h4 id=&#34;1-mpmc-的两头肉搏到底有多痛&#34;&gt;1. MPMC 的“两头肉搏”到底有多痛？&lt;/h4&gt;
&lt;p&gt;在 MPMC 中，所有生产者和消费者都盯着&lt;strong&gt;同一个头指针（Head）&lt;strong&gt;和&lt;/strong&gt;同一个尾指针（Tail）&lt;/strong&gt;。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;生产者肉搏&lt;/strong&gt;：N 个生产者疯狂 CAS 抢 &lt;code&gt;Head&lt;/code&gt;（分配槽位）。每次 CAS 都是 RFO（Read For Ownership），导致 &lt;code&gt;Head&lt;/code&gt; 所在的缓存行在 N 个核心间“乒乓”。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;消费者肉搏&lt;/strong&gt;：M 个消费者疯狂 CAS 抢 &lt;code&gt;Tail&lt;/code&gt;（消费进度）。同样导致缓存行在 M 个核心间“乒乓”。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;头尾互搏&lt;/strong&gt;：更恐怖的是，&lt;code&gt;Head&lt;/code&gt; 和 &lt;code&gt;Tail&lt;/code&gt; 如果在同一个缓存行（False Sharing），生产者抢 Head 还会顺便把 Tail 的缓存行弄脏，直接拖垮消费者。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;结果&lt;/strong&gt;：吞吐量随着核心数增加&lt;strong&gt;不升反降&lt;/strong&gt;，延迟飙升到微秒级。&lt;/p&gt;
&lt;hr&gt;
&lt;h4 id=&#34;2-顶级框架-lmax-disruptor-的核心理念&#34;&gt;2. 顶级框架 LMAX Disruptor 的“核心理念”&lt;/h4&gt;
&lt;p&gt;LMAX 是金融交易系统（每秒处理 600 万笔订单），它解决 MPMC 的思路极其高明，核心就两招：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;干掉竞争（CAS）&lt;/strong&gt;：用&lt;strong&gt;顺序分配 + 栅栏（Barrier）&lt;strong&gt;代替互斥。生产者不抢同一个指针，而是&lt;/strong&gt;各自申请一段连续的空间&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;干掉伪共享&lt;/strong&gt;：&lt;strong&gt;缓存行填充（Cache Line Padding）&lt;/strong&gt;，让 Head、Tail、Cursor 老死不相往来。&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h4 id=&#34;3-核心机制申请claim与-发布publish&#34;&gt;3. 核心机制：申请（Claim）与 发布（Publish）&lt;/h4&gt;
&lt;p&gt;Disruptor 不直接操作指针，而是通过&lt;strong&gt;序号（Sequence）&lt;/strong&gt;：&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
