<?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>Gil on Tarragon</title><link>https://tarrragon.github.io/blog/tags/gil/</link><description>Recent content in Gil on Tarragon</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><copyright>Tarragon (CC BY 4.0)</copyright><lastBuildDate>Fri, 19 Jun 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/tags/gil/index.xml" rel="self" type="application/rss+xml"/><item><title>Python 平台適配</title><link>https://tarrragon.github.io/blog/monitoring/05-platform-adaptation/python-platform/</link><pubDate>Fri, 19 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/monitoring/05-platform-adaptation/python-platform/</guid><description>&lt;p>Python 的執行模型（GIL 限制並行、atexit 不保證執行、subprocess 獨立 process）讓監控 SDK 在 Python 環境中需要特別處理 flush 的執行方式、程序退出時的事件保存和子程序的監控。&lt;/p>
&lt;h2 id="gil-與-threading">GIL 與 threading&lt;/h2>
&lt;p>Python 的 Global Interpreter Lock（GIL）讓同一時間只有一個 thread 執行 Python bytecode。SDK 的 flush 操作（HTTP POST 到 collector）如果在主 thread 執行，會阻塞主程式的其他工作。&lt;/p>
&lt;p>SDK 端的適配：&lt;/p>
&lt;p>在 daemon thread 中執行 flush。Daemon thread 在主 thread 結束時自動終止，不需要手動 join。SDK 的 flush 計時器在 daemon thread 中運行，buffer 的存取用 threading.Lock 保護。&lt;/p>
&lt;p>GIL 對 SDK 的影響比想像的小：HTTP 請求是 I/O bound 操作，CPython 在等待 I/O 時釋放 GIL。所以 flush 的 HTTP POST 在 daemon thread 中執行時，主 thread 可以繼續工作。GIL 只在 CPU-bound 的操作上造成瓶頸 — SDK 的 buffer 操作和事件序列化是 CPU-bound 但耗時極短（微秒級），影響可忽略。&lt;/p>
&lt;h3 id="asyncio-環境">asyncio 環境&lt;/h3>
&lt;p>Python 的 asyncio 程式（FastAPI、aiohttp）使用事件迴圈而非 threading。SDK 在 asyncio 環境中應該用 &lt;code>asyncio.create_task&lt;/code> 而非 threading 執行 flush，避免在事件迴圈中阻塞。&lt;/p>
&lt;p>SDK 可以在 init 時自動偵測是否在 asyncio 環境中（檢查 &lt;code>asyncio.get_running_loop()&lt;/code> 是否存在），自動切換 flush 的執行方式。&lt;/p>
&lt;h2 id="atexit-可靠性">atexit 可靠性&lt;/h2>
&lt;p>&lt;code>atexit.register&lt;/code> 在 Python 程序正常退出時執行註冊的清理函式。SDK 在 init 時註冊 atexit handler 做最後一次 flush。&lt;/p>
&lt;p>atexit 不執行的場景：&lt;/p>
&lt;ul>
&lt;li>&lt;code>os._exit()&lt;/code> 直接終止 process，跳過所有清理&lt;/li>
&lt;li>SIGKILL（&lt;code>kill -9&lt;/code>）強制終止，作業系統直接回收 process&lt;/li>
&lt;li>未處理的 fatal signal（SIGSEGV、SIGABRT）導致 crash&lt;/li>
&lt;/ul>
&lt;p>對於 SIGTERM 和 SIGINT，Python 預設會執行 atexit handler（前提是 signal handler 沒有被覆蓋）。SDK 可以額外註冊 &lt;code>signal.signal(signal.SIGTERM, handler)&lt;/code> 確保在收到 SIGTERM 時觸發 flush。&lt;/p>
&lt;p>實務影響：&lt;code>os._exit()&lt;/code> 和 SIGKILL 導致的事件遺失無法避免。使用本地 persistence（&lt;a href="https://tarrragon.github.io/blog/monitoring/03-sdk-design/offline-buffer/" data-link-title="離線 buffer 與重試" data-link-desc="網路不可用時的事件保存策略 — FIFO 丟棄、本地 persistence、恢復後補發的取捨">離線 buffer&lt;/a>）可以降低影響 — 事件在寫入本地檔案後，即使 process 被強制終止，下次啟動時仍可補發。&lt;/p>
&lt;h2 id="短生命週期腳本">短生命週期腳本&lt;/h2>
&lt;p>SDK 的預設設計假設長期運行的 app — flush interval 定期觸發、daemon thread 持續運行、atexit 是最後防線。但 Python SDK 的一個重要場景是短命腳本（CI/CD hook、pre-commit hook、CLI 工具的子命令），生命週期可能 &amp;lt; 1 秒。這個場景下 SDK 的行為和長期 app 完全不同。&lt;/p>
&lt;h3 id="什麼會壞">什麼會壞&lt;/h3>
&lt;p>&lt;strong>flush interval 來不及觸發&lt;/strong>。預設 30 秒的 flush interval，但腳本在 200ms 內結束。計時器還沒觸發，buffer 中的事件從未送出。&lt;/p></description><content:encoded><![CDATA[<p>Python 的執行模型（GIL 限制並行、atexit 不保證執行、subprocess 獨立 process）讓監控 SDK 在 Python 環境中需要特別處理 flush 的執行方式、程序退出時的事件保存和子程序的監控。</p>
<h2 id="gil-與-threading">GIL 與 threading</h2>
<p>Python 的 Global Interpreter Lock（GIL）讓同一時間只有一個 thread 執行 Python bytecode。SDK 的 flush 操作（HTTP POST 到 collector）如果在主 thread 執行，會阻塞主程式的其他工作。</p>
<p>SDK 端的適配：</p>
<p>在 daemon thread 中執行 flush。Daemon thread 在主 thread 結束時自動終止，不需要手動 join。SDK 的 flush 計時器在 daemon thread 中運行，buffer 的存取用 threading.Lock 保護。</p>
<p>GIL 對 SDK 的影響比想像的小：HTTP 請求是 I/O bound 操作，CPython 在等待 I/O 時釋放 GIL。所以 flush 的 HTTP POST 在 daemon thread 中執行時，主 thread 可以繼續工作。GIL 只在 CPU-bound 的操作上造成瓶頸 — SDK 的 buffer 操作和事件序列化是 CPU-bound 但耗時極短（微秒級），影響可忽略。</p>
<h3 id="asyncio-環境">asyncio 環境</h3>
<p>Python 的 asyncio 程式（FastAPI、aiohttp）使用事件迴圈而非 threading。SDK 在 asyncio 環境中應該用 <code>asyncio.create_task</code> 而非 threading 執行 flush，避免在事件迴圈中阻塞。</p>
<p>SDK 可以在 init 時自動偵測是否在 asyncio 環境中（檢查 <code>asyncio.get_running_loop()</code> 是否存在），自動切換 flush 的執行方式。</p>
<h2 id="atexit-可靠性">atexit 可靠性</h2>
<p><code>atexit.register</code> 在 Python 程序正常退出時執行註冊的清理函式。SDK 在 init 時註冊 atexit handler 做最後一次 flush。</p>
<p>atexit 不執行的場景：</p>
<ul>
<li><code>os._exit()</code> 直接終止 process，跳過所有清理</li>
<li>SIGKILL（<code>kill -9</code>）強制終止，作業系統直接回收 process</li>
<li>未處理的 fatal signal（SIGSEGV、SIGABRT）導致 crash</li>
</ul>
<p>對於 SIGTERM 和 SIGINT，Python 預設會執行 atexit handler（前提是 signal handler 沒有被覆蓋）。SDK 可以額外註冊 <code>signal.signal(signal.SIGTERM, handler)</code> 確保在收到 SIGTERM 時觸發 flush。</p>
<p>實務影響：<code>os._exit()</code> 和 SIGKILL 導致的事件遺失無法避免。使用本地 persistence（<a href="/blog/monitoring/03-sdk-design/offline-buffer/" data-link-title="離線 buffer 與重試" data-link-desc="網路不可用時的事件保存策略 — FIFO 丟棄、本地 persistence、恢復後補發的取捨">離線 buffer</a>）可以降低影響 — 事件在寫入本地檔案後，即使 process 被強制終止，下次啟動時仍可補發。</p>
<h2 id="短生命週期腳本">短生命週期腳本</h2>
<p>SDK 的預設設計假設長期運行的 app — flush interval 定期觸發、daemon thread 持續運行、atexit 是最後防線。但 Python SDK 的一個重要場景是短命腳本（CI/CD hook、pre-commit hook、CLI 工具的子命令），生命週期可能 &lt; 1 秒。這個場景下 SDK 的行為和長期 app 完全不同。</p>
<h3 id="什麼會壞">什麼會壞</h3>
<p><strong>flush interval 來不及觸發</strong>。預設 30 秒的 flush interval，但腳本在 200ms 內結束。計時器還沒觸發，buffer 中的事件從未送出。</p>
<p><strong>daemon thread 隨主 thread 結束</strong>。SDK 用 daemon thread 執行 flush 計時器。Python 的 daemon thread 在最後一個非 daemon thread 結束時被殺 — 不會等待 daemon thread 完成當前工作。如果 flush 正在進行中（HTTP POST 送到一半），daemon thread 被殺，HTTP 請求中斷，事件丟失。</p>
<p><strong>atexit 的執行順序不確定</strong>。atexit handler 在 daemon thread 被殺之後執行。如果 SDK 的 atexit handler 嘗試在 daemon thread 中 flush，會失敗（thread 已死）。atexit handler 必須在主 thread 中同步 flush。</p>
<h3 id="正確的短命腳本模式">正確的短命腳本模式</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln">1</span><span class="cl"><span class="kn">from</span> <span class="nn">monitor</span> <span class="kn">import</span> <span class="n">Monitor</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="n">Monitor</span><span class="o">.</span><span class="n">init</span><span class="p">(</span><span class="n">endpoint</span><span class="o">=</span><span class="s2">&#34;http://localhost:9090/v1/events&#34;</span><span class="p">,</span> <span class="n">app</span><span class="o">=</span><span class="s2">&#34;my-hook&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="c1"># 做事...</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="n">Monitor</span><span class="o">.</span><span class="n">event</span><span class="p">(</span><span class="s2">&#34;hook.run&#34;</span><span class="p">,</span> <span class="p">{</span><span class="s2">&#34;hook&#34;</span><span class="p">:</span> <span class="s2">&#34;branch-check&#34;</span><span class="p">})</span>
</span></span><span class="line"><span class="ln">7</span><span class="cl">
</span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="c1"># 結束前必須呼叫 close</span>
</span></span><span class="line"><span class="ln">9</span><span class="cl"><span class="n">Monitor</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>  <span class="c1"># close 內同步 flush，不依賴 daemon thread</span></span></span></code></pre></div><p><code>close()</code> 是唯一可靠的 flush 時機。<code>close()</code> 的實作在短命腳本場景下必須：</p>
<ol>
<li><strong>同步執行 HTTP POST</strong>，不委託給 daemon thread — 主 thread 呼叫 <code>close()</code> 時直接在當前 thread 送出</li>
<li><strong>設 HTTP timeout</strong> — 短命腳本不能等太久，3 秒的 timeout 是合理的</li>
<li><strong>flush 失敗時靜默放棄</strong> — 短命腳本的主要職責不是監控，SDK 失敗不應影響腳本的 exit code</li>
</ol>
<p><code>atexit</code> 仍然註冊，作為開發者忘記呼叫 <code>close()</code> 的備份。但 atexit 是 best-effort — 在 <code>os._exit()</code> 和 SIGKILL 下不執行。</p>
<h3 id="flush-interval-在短命腳本中的角色">flush interval 在短命腳本中的角色</h3>
<p>flush interval 對短命腳本無意義 — 腳本在第一次 interval 觸發前就結束了。SDK 可以偵測「init 到 close 的間隔 &lt; flush interval」的模式，在 debug log 中提示開發者考慮降低 interval 或直接依賴 <code>close()</code> flush。</p>
<p>但不建議把 flush interval 設為 0（停用）— 同一個 SDK 設定可能同時用於長期 app 和短命腳本，interval 對長期 app 仍然有用。</p>
<h2 id="subprocess-監控">Subprocess 監控</h2>
<p>Python 程式中的 <code>subprocess.Popen</code> 啟動的子程序是獨立的 process，不共享 SDK 的 buffer 和網路連線。子程序的錯誤和事件需要獨立的監控機制。</p>
<p>兩種方式：</p>
<p><strong>子程序獨立初始化 SDK</strong>：子程序的 Python 腳本自己呼叫 <code>Monitor.init()</code>，獨立送事件到 collector。適合子程序是長時間運行的 Python 程式。</p>
<p><strong>父程序代理</strong>：父程序讀取子程序的 stdout/stderr，從輸出中解析事件（子程序用約定格式印出事件），父程序的 SDK 代理送出。適合子程序是短命的腳本或非 Python 程式。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>Go 平台的適配 → <a href="/blog/monitoring/05-platform-adaptation/go-platform/" data-link-title="Go 平台適配" data-link-desc="Graceful shutdown、signal handling、HTTP server 自身監控 — Go SDK 和 collector 端共同面對的平台問題">Go 平台適配</a></li>
<li>跨平台 timestamp 一致性 → <a href="/blog/monitoring/05-platform-adaptation/cross-platform-timestamp/" data-link-title="跨平台 timestamp 一致性" data-link-desc="時區、精度、clock drift — 不同平台產生的 timestamp 在 collector 端需要能正確比對和排序">跨平台 timestamp 一致性</a></li>
<li>離線 buffer 策略 → <a href="/blog/monitoring/03-sdk-design/offline-buffer/" data-link-title="離線 buffer 與重試" data-link-desc="網路不可用時的事件保存策略 — FIFO 丟棄、本地 persistence、恢復後補發的取捨">模組三 離線 buffer 與重試</a></li>
</ul>
]]></content:encoded></item><item><title>3.4 GIL 與執行緒模型</title><link>https://tarrragon.github.io/blog/python-advanced/04-cpython-internals/gil-threading/</link><pubDate>Tue, 20 Jan 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/python-advanced/04-cpython-internals/gil-threading/</guid><description>&lt;p>GIL（Global Interpreter Lock）是 CPython 中最具爭議的設計之一。本章深入探討 GIL 的歷史、實現，以及 Python 3.13+ Free-threading 的技術細節。&lt;/p>
&lt;h2 id="先備知識">先備知識&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/python-advanced/04-cpython-internals/bytecode/" data-link-title="3.3 Bytecode 與虛擬機" data-link-desc="理解 Python 的執行過程">3.3 Bytecode 與虛擬機&lt;/a>&lt;/li>
&lt;li>入門系列 &lt;a href="https://tarrragon.github.io/blog/python/03-stdlib/concurrency/" data-link-title="3.7 並行處理 - threading、multiprocessing、concurrent.futures" data-link-desc="Python 並行處理的三種方式與選擇指南">3.7 並行處理&lt;/a>&lt;/li>
&lt;li>入門系列 &lt;a href="https://tarrragon.github.io/blog/python-advanced/04-cpython-internals/free-threading/" data-link-title="4.5 Free-Threading - Python 的真正多執行緒時代" data-link-desc="Python 3.13&amp;#43; 無 GIL 版本的完整指南">3.8 Free-Threading&lt;/a>&lt;/li>
&lt;/ul>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>學完本章後，你將能夠：&lt;/p>
&lt;ol>
&lt;li>理解 GIL 存在的歷史原因&lt;/li>
&lt;li>理解 GIL 的釋放時機&lt;/li>
&lt;li>理解 Free-threading 的實現挑戰&lt;/li>
&lt;li>做出正確的並行策略選擇&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="原理層為什麼需要-gil">【原理層】為什麼需要 GIL？&lt;/h2>
&lt;h3 id="歷史背景">歷史背景&lt;/h3>
&lt;p>GIL 是 1992 年 Python 初創時的設計決策：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">當時的考量：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">1. 單核 CPU 是主流
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">2. 簡化記憶體管理（參考計數）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">3. 簡化 C 擴展開發
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">4. 避免細粒度鎖的複雜性&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="參考計數與執行緒安全">參考計數與執行緒安全&lt;/h3>
&lt;p>GIL 主要保護參考計數操作：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="c1">// 沒有 GIL 時，這個操作不是原子的
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="nf">Py_INCREF&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">obj&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">&lt;span class="c1">// 展開後：
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="c1">// 1. 讀取 ob_refcnt
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">&lt;span class="c1">// 2. 加 1
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">&lt;span class="c1">// 3. 寫回 ob_refcnt
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">&lt;span class="c1">// 如果兩個執行緒同時執行，可能會：
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="c1">// Thread 1: 讀取 refcnt = 1
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">&lt;span class="c1">// Thread 2: 讀取 refcnt = 1
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">&lt;span class="c1">// Thread 1: 寫入 refcnt = 2
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">&lt;span class="c1">// Thread 2: 寫入 refcnt = 2 ← 錯誤！應該是 3
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="gil-的實現">GIL 的實現&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="c1">// 簡化版的 GIL 結構
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="k">typedef&lt;/span> &lt;span class="k">struct&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl"> &lt;span class="n">PyMutex&lt;/span> &lt;span class="n">mutex&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// 互斥鎖
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">PyThread_type_lock&lt;/span> &lt;span class="n">lock&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// 執行緒鎖
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">int&lt;/span> &lt;span class="n">locked&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// 鎖定狀態
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="p">}&lt;/span> &lt;span class="n">_gil_runtime_state&lt;/span>&lt;span class="p">;&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;h2 id="設計層gil-的釋放時機">【設計層】GIL 的釋放時機&lt;/h2>
&lt;h3 id="自動釋放">自動釋放&lt;/h3>
&lt;p>GIL 在以下情況會自動釋放：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 1. I/O 操作&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">&lt;span class="n">f&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">open&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;file.txt&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;r&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># 釋放 GIL&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">&lt;span class="n">content&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">read&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="c1"># 釋放 GIL&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">&lt;span class="c1"># 2. sleep&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">time&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">&lt;span class="n">time&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sleep&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># 釋放 GIL&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="c1"># 3. 某些 C 擴展操作&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">numpy&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="nn">np&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">&lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">dot&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">a&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># NumPy 可能釋放 GIL&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl">&lt;span class="c1"># 4. 定期釋放（每 N 個 bytecode 指令）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl">&lt;span class="c1"># Python 3.2+ 預設約每 5ms 檢查一次&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="檢查間隔">檢查間隔&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">sys&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">&lt;span class="c1"># 查看切換間隔（秒）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">sys&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getswitchinterval&lt;/span>&lt;span class="p">())&lt;/span> &lt;span class="c1"># 0.005（5ms）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">&lt;span class="c1"># 設定切換間隔&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">&lt;span class="n">sys&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">setswitchinterval&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mf">0.001&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># 1ms&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="c-擴展中手動釋放-gil">C 擴展中手動釋放 GIL&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="c1">// C 擴展可以明確釋放 GIL
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="k">static&lt;/span> &lt;span class="n">PyObject&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="nf">compute_intensive&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">PyObject&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">PyObject&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">args&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 釋放 GIL
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">Py_BEGIN_ALLOW_THREADS&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 這裡的程式碼可以並行執行
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="nf">do_heavy_computation&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 重新獲取 GIL
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">Py_END_ALLOW_THREADS&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl"> &lt;span class="n">Py_RETURN_NONE&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;h2 id="實驗測量-gil-的影響">【實驗】測量 GIL 的影響&lt;/h2>
&lt;h3 id="cpu-密集任務">CPU 密集任務&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">threading&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">time&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">cpu_intensive&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">n&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;純 Python CPU 密集計算&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl"> &lt;span class="n">total&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="nb">range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">n&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl"> &lt;span class="n">total&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">i&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">total&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">benchmark&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">func&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">args&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">num_threads&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl"> &lt;span class="n">threads&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl"> &lt;span class="n">start&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">time&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">perf_counter&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">_&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="nb">range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">num_threads&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl"> &lt;span class="n">t&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">threading&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">Thread&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">func&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">args&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">args&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl"> &lt;span class="n">threads&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">t&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">18&lt;/span>&lt;span class="cl"> &lt;span class="n">t&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">start&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">19&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">20&lt;/span>&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">t&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">threads&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">21&lt;/span>&lt;span class="cl"> &lt;span class="n">t&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">join&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">22&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">23&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">time&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">perf_counter&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">start&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">24&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">25&lt;/span>&lt;span class="cl">&lt;span class="n">n&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">5_000_000&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">26&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">27&lt;/span>&lt;span class="cl">&lt;span class="c1"># 單執行緒&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">28&lt;/span>&lt;span class="cl">&lt;span class="n">time_1&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">benchmark&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">cpu_intensive&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">n&lt;/span>&lt;span class="p">,),&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">29&lt;/span>&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;1 執行緒: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">time_1&lt;/span>&lt;span class="si">:&lt;/span>&lt;span class="s2">.3f&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">s&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">30&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">31&lt;/span>&lt;span class="cl">&lt;span class="c1"># 多執行緒（受 GIL 限制）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">32&lt;/span>&lt;span class="cl">&lt;span class="n">time_4&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">benchmark&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">cpu_intensive&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">n&lt;/span>&lt;span class="p">,),&lt;/span> &lt;span class="mi">4&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">33&lt;/span>&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;4 執行緒: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">time_4&lt;/span>&lt;span class="si">:&lt;/span>&lt;span class="s2">.3f&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">s&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">34&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">35&lt;/span>&lt;span class="cl">&lt;span class="c1"># 結果：多執行緒可能更慢（執行緒切換開銷）&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="io-密集任務">I/O 密集任務&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">threading&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">time&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">urllib.request&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">io_intensive&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;I/O 密集操作&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl"> &lt;span class="k">try&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl"> &lt;span class="k">with&lt;/span> &lt;span class="n">urllib&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">request&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">urlopen&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">timeout&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">5&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="nb">len&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">read&lt;/span>&lt;span class="p">())&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl"> &lt;span class="k">except&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="mi">0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl">&lt;span class="n">urls&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;https://example.com&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="mi">10&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl">&lt;span class="c1"># 單執行緒&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl">&lt;span class="n">start&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">time&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">perf_counter&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl">&lt;span class="k">for&lt;/span> &lt;span class="n">url&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">urls&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">18&lt;/span>&lt;span class="cl"> &lt;span class="n">io_intensive&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">19&lt;/span>&lt;span class="cl">&lt;span class="n">time_sequential&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">time&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">perf_counter&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">start&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">20&lt;/span>&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;序列: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">time_sequential&lt;/span>&lt;span class="si">:&lt;/span>&lt;span class="s2">.3f&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">s&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">21&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">22&lt;/span>&lt;span class="cl">&lt;span class="c1"># 多執行緒&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">23&lt;/span>&lt;span class="cl">&lt;span class="n">start&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">time&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">perf_counter&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">24&lt;/span>&lt;span class="cl">&lt;span class="n">threads&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="n">threading&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">Thread&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">io_intensive&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">args&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,))&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="n">url&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">urls&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">25&lt;/span>&lt;span class="cl">&lt;span class="k">for&lt;/span> &lt;span class="n">t&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">threads&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">26&lt;/span>&lt;span class="cl"> &lt;span class="n">t&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">start&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">27&lt;/span>&lt;span class="cl">&lt;span class="k">for&lt;/span> &lt;span class="n">t&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">threads&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">28&lt;/span>&lt;span class="cl"> &lt;span class="n">t&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">join&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">29&lt;/span>&lt;span class="cl">&lt;span class="n">time_parallel&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">time&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">perf_counter&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">start&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">30&lt;/span>&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;並行: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">time_parallel&lt;/span>&lt;span class="si">:&lt;/span>&lt;span class="s2">.3f&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">s&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">31&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">32&lt;/span>&lt;span class="cl">&lt;span class="c1"># 結果：多執行緒明顯更快（I/O 時釋放 GIL）&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;h2 id="深入free-threading-技術細節">【深入】Free-threading 技術細節&lt;/h2>
&lt;h3 id="biased-reference-counting">Biased Reference Counting&lt;/h3>
&lt;p>Python 3.13+ Free-threading 使用「偏向參考計數」解決多執行緒問題：&lt;/p></description><content:encoded><![CDATA[<p>GIL（Global Interpreter Lock）是 CPython 中最具爭議的設計之一。本章深入探討 GIL 的歷史、實現，以及 Python 3.13+ Free-threading 的技術細節。</p>
<h2 id="先備知識">先備知識</h2>
<ul>
<li><a href="/blog/python-advanced/04-cpython-internals/bytecode/" data-link-title="3.3 Bytecode 與虛擬機" data-link-desc="理解 Python 的執行過程">3.3 Bytecode 與虛擬機</a></li>
<li>入門系列 <a href="/blog/python/03-stdlib/concurrency/" data-link-title="3.7 並行處理 - threading、multiprocessing、concurrent.futures" data-link-desc="Python 並行處理的三種方式與選擇指南">3.7 並行處理</a></li>
<li>入門系列 <a href="/blog/python-advanced/04-cpython-internals/free-threading/" data-link-title="4.5 Free-Threading - Python 的真正多執行緒時代" data-link-desc="Python 3.13&#43; 無 GIL 版本的完整指南">3.8 Free-Threading</a></li>
</ul>
<h2 id="本章目標">本章目標</h2>
<p>學完本章後，你將能夠：</p>
<ol>
<li>理解 GIL 存在的歷史原因</li>
<li>理解 GIL 的釋放時機</li>
<li>理解 Free-threading 的實現挑戰</li>
<li>做出正確的並行策略選擇</li>
</ol>
<hr>
<h2 id="原理層為什麼需要-gil">【原理層】為什麼需要 GIL？</h2>
<h3 id="歷史背景">歷史背景</h3>
<p>GIL 是 1992 年 Python 初創時的設計決策：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">當時的考量：
</span></span><span class="line"><span class="ln">2</span><span class="cl">1. 單核 CPU 是主流
</span></span><span class="line"><span class="ln">3</span><span class="cl">2. 簡化記憶體管理（參考計數）
</span></span><span class="line"><span class="ln">4</span><span class="cl">3. 簡化 C 擴展開發
</span></span><span class="line"><span class="ln">5</span><span class="cl">4. 避免細粒度鎖的複雜性</span></span></code></pre></div><h3 id="參考計數與執行緒安全">參考計數與執行緒安全</h3>
<p>GIL 主要保護參考計數操作：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1">// 沒有 GIL 時，這個操作不是原子的
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="c1"></span><span class="nf">Py_INCREF</span><span class="p">(</span><span class="n">obj</span><span class="p">);</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="c1">// 展開後：
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="c1">// 1. 讀取 ob_refcnt
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="c1">// 2. 加 1
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="c1">// 3. 寫回 ob_refcnt
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="c1">// 如果兩個執行緒同時執行，可能會：
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="c1">// Thread 1: 讀取 refcnt = 1
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="c1">// Thread 2: 讀取 refcnt = 1
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="c1">// Thread 1: 寫入 refcnt = 2
</span></span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="c1">// Thread 2: 寫入 refcnt = 2  ← 錯誤！應該是 3
</span></span></span></code></pre></div><h3 id="gil-的實現">GIL 的實現</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1">// 簡化版的 GIL 結構
</span></span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"></span><span class="k">typedef</span> <span class="k">struct</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">    <span class="n">PyMutex</span> <span class="n">mutex</span><span class="p">;</span>           <span class="c1">// 互斥鎖
</span></span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"></span>    <span class="n">PyThread_type_lock</span> <span class="n">lock</span><span class="p">;</span> <span class="c1">// 執行緒鎖
</span></span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="c1"></span>    <span class="kt">int</span> <span class="n">locked</span><span class="p">;</span>              <span class="c1">// 鎖定狀態
</span></span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="c1"></span><span class="p">}</span> <span class="n">_gil_runtime_state</span><span class="p">;</span></span></span></code></pre></div><hr>
<h2 id="設計層gil-的釋放時機">【設計層】GIL 的釋放時機</h2>
<h3 id="自動釋放">自動釋放</h3>
<p>GIL 在以下情況會自動釋放：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># 1. I/O 操作</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="n">f</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s1">&#39;file.txt&#39;</span><span class="p">,</span> <span class="s1">&#39;r&#39;</span><span class="p">)</span>  <span class="c1"># 釋放 GIL</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="n">content</span> <span class="o">=</span> <span class="n">f</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>          <span class="c1"># 釋放 GIL</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="c1"># 2. sleep</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="kn">import</span> <span class="nn">time</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>  <span class="c1"># 釋放 GIL</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="c1"># 3. 某些 C 擴展操作</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="nn">np</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="n">result</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">dot</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">)</span>  <span class="c1"># NumPy 可能釋放 GIL</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="c1"># 4. 定期釋放（每 N 個 bytecode 指令）</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="c1"># Python 3.2+ 預設約每 5ms 檢查一次</span></span></span></code></pre></div><h3 id="檢查間隔">檢查間隔</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln">1</span><span class="cl"><span class="kn">import</span> <span class="nn">sys</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="c1"># 查看切換間隔（秒）</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">getswitchinterval</span><span class="p">())</span>  <span class="c1"># 0.005（5ms）</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">
</span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="c1"># 設定切換間隔</span>
</span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="n">sys</span><span class="o">.</span><span class="n">setswitchinterval</span><span class="p">(</span><span class="mf">0.001</span><span class="p">)</span>  <span class="c1"># 1ms</span></span></span></code></pre></div><h3 id="c-擴展中手動釋放-gil">C 擴展中手動釋放 GIL</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1">// C 擴展可以明確釋放 GIL
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="c1"></span><span class="k">static</span> <span class="n">PyObject</span><span class="o">*</span> <span class="nf">compute_intensive</span><span class="p">(</span><span class="n">PyObject</span><span class="o">*</span> <span class="n">self</span><span class="p">,</span> <span class="n">PyObject</span><span class="o">*</span> <span class="n">args</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">    <span class="c1">// 釋放 GIL
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="c1"></span>    <span class="n">Py_BEGIN_ALLOW_THREADS</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">    <span class="c1">// 這裡的程式碼可以並行執行
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="c1"></span>    <span class="nf">do_heavy_computation</span><span class="p">();</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    <span class="c1">// 重新獲取 GIL
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="c1"></span>    <span class="n">Py_END_ALLOW_THREADS</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">
</span></span><span class="line"><span class="ln">12</span><span class="cl">    <span class="n">Py_RETURN_NONE</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><hr>
<h2 id="實驗測量-gil-的影響">【實驗】測量 GIL 的影響</h2>
<h3 id="cpu-密集任務">CPU 密集任務</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">import</span> <span class="nn">threading</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="kn">import</span> <span class="nn">time</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="k">def</span> <span class="nf">cpu_intensive</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="s2">&#34;&#34;&#34;純 Python CPU 密集計算&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">    <span class="n">total</span> <span class="o">=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">        <span class="n">total</span> <span class="o">+=</span> <span class="n">i</span> <span class="o">*</span> <span class="n">i</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    <span class="k">return</span> <span class="n">total</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="k">def</span> <span class="nf">benchmark</span><span class="p">(</span><span class="n">func</span><span class="p">,</span> <span class="n">args</span><span class="p">,</span> <span class="n">num_threads</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">    <span class="n">threads</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">    <span class="n">start</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">perf_counter</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">
</span></span><span class="line"><span class="ln">15</span><span class="cl">    <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">num_threads</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">        <span class="n">t</span> <span class="o">=</span> <span class="n">threading</span><span class="o">.</span><span class="n">Thread</span><span class="p">(</span><span class="n">target</span><span class="o">=</span><span class="n">func</span><span class="p">,</span> <span class="n">args</span><span class="o">=</span><span class="n">args</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">        <span class="n">threads</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">t</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">        <span class="n">t</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">
</span></span><span class="line"><span class="ln">20</span><span class="cl">    <span class="k">for</span> <span class="n">t</span> <span class="ow">in</span> <span class="n">threads</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">        <span class="n">t</span><span class="o">.</span><span class="n">join</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">
</span></span><span class="line"><span class="ln">23</span><span class="cl">    <span class="k">return</span> <span class="n">time</span><span class="o">.</span><span class="n">perf_counter</span><span class="p">()</span> <span class="o">-</span> <span class="n">start</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">
</span></span><span class="line"><span class="ln">25</span><span class="cl"><span class="n">n</span> <span class="o">=</span> <span class="mi">5_000_000</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl">
</span></span><span class="line"><span class="ln">27</span><span class="cl"><span class="c1"># 單執行緒</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl"><span class="n">time_1</span> <span class="o">=</span> <span class="n">benchmark</span><span class="p">(</span><span class="n">cpu_intensive</span><span class="p">,</span> <span class="p">(</span><span class="n">n</span><span class="p">,),</span> <span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">29</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;1 執行緒: </span><span class="si">{</span><span class="n">time_1</span><span class="si">:</span><span class="s2">.3f</span><span class="si">}</span><span class="s2">s&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl">
</span></span><span class="line"><span class="ln">31</span><span class="cl"><span class="c1"># 多執行緒（受 GIL 限制）</span>
</span></span><span class="line"><span class="ln">32</span><span class="cl"><span class="n">time_4</span> <span class="o">=</span> <span class="n">benchmark</span><span class="p">(</span><span class="n">cpu_intensive</span><span class="p">,</span> <span class="p">(</span><span class="n">n</span><span class="p">,),</span> <span class="mi">4</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">33</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;4 執行緒: </span><span class="si">{</span><span class="n">time_4</span><span class="si">:</span><span class="s2">.3f</span><span class="si">}</span><span class="s2">s&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">34</span><span class="cl">
</span></span><span class="line"><span class="ln">35</span><span class="cl"><span class="c1"># 結果：多執行緒可能更慢（執行緒切換開銷）</span></span></span></code></pre></div><h3 id="io-密集任務">I/O 密集任務</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">import</span> <span class="nn">threading</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="kn">import</span> <span class="nn">time</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="kn">import</span> <span class="nn">urllib.request</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="k">def</span> <span class="nf">io_intensive</span><span class="p">(</span><span class="n">url</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">    <span class="s2">&#34;&#34;&#34;I/O 密集操作&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">    <span class="k">try</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">        <span class="k">with</span> <span class="n">urllib</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">urlopen</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">timeout</span><span class="o">=</span><span class="mi">5</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">            <span class="k">return</span> <span class="nb">len</span><span class="p">(</span><span class="n">f</span><span class="o">.</span><span class="n">read</span><span class="p">())</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="k">except</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">        <span class="k">return</span> <span class="mi">0</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="n">urls</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&#34;https://example.com&#34;</span><span class="p">]</span> <span class="o">*</span> <span class="mi">10</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">
</span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="c1"># 單執行緒</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="n">start</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">perf_counter</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">urls</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">    <span class="n">io_intensive</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="n">time_sequential</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">perf_counter</span><span class="p">()</span> <span class="o">-</span> <span class="n">start</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;序列: </span><span class="si">{</span><span class="n">time_sequential</span><span class="si">:</span><span class="s2">.3f</span><span class="si">}</span><span class="s2">s&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">
</span></span><span class="line"><span class="ln">22</span><span class="cl"><span class="c1"># 多執行緒</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl"><span class="n">start</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">perf_counter</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl"><span class="n">threads</span> <span class="o">=</span> <span class="p">[</span><span class="n">threading</span><span class="o">.</span><span class="n">Thread</span><span class="p">(</span><span class="n">target</span><span class="o">=</span><span class="n">io_intensive</span><span class="p">,</span> <span class="n">args</span><span class="o">=</span><span class="p">(</span><span class="n">url</span><span class="p">,))</span> <span class="k">for</span> <span class="n">url</span> <span class="ow">in</span> <span class="n">urls</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl"><span class="k">for</span> <span class="n">t</span> <span class="ow">in</span> <span class="n">threads</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl">    <span class="n">t</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl"><span class="k">for</span> <span class="n">t</span> <span class="ow">in</span> <span class="n">threads</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl">    <span class="n">t</span><span class="o">.</span><span class="n">join</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">29</span><span class="cl"><span class="n">time_parallel</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">perf_counter</span><span class="p">()</span> <span class="o">-</span> <span class="n">start</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;並行: </span><span class="si">{</span><span class="n">time_parallel</span><span class="si">:</span><span class="s2">.3f</span><span class="si">}</span><span class="s2">s&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">31</span><span class="cl">
</span></span><span class="line"><span class="ln">32</span><span class="cl"><span class="c1"># 結果：多執行緒明顯更快（I/O 時釋放 GIL）</span></span></span></code></pre></div><hr>
<h2 id="深入free-threading-技術細節">【深入】Free-threading 技術細節</h2>
<h3 id="biased-reference-counting">Biased Reference Counting</h3>
<p>Python 3.13+ Free-threading 使用「偏向參考計數」解決多執行緒問題：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">傳統參考計數：
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">┌─────────────────────────────────────┐
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">│  ob_refcnt = 2                      │
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">│  每次操作都需要原子操作或鎖         │
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">└─────────────────────────────────────┘
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">偏向參考計數：
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">┌─────────────────────────────────────┐
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">│  local_refcnt[thread_id] = 1        │  ← 每個執行緒有自己的計數
</span></span><span class="line"><span class="ln">10</span><span class="cl">│  local_refcnt[thread_id] = 1        │
</span></span><span class="line"><span class="ln">11</span><span class="cl">│  shared_refcnt = 0                  │  ← 共享計數
</span></span><span class="line"><span class="ln">12</span><span class="cl">└─────────────────────────────────────┘
</span></span><span class="line"><span class="ln">13</span><span class="cl">
</span></span><span class="line"><span class="ln">14</span><span class="cl">優點：
</span></span><span class="line"><span class="ln">15</span><span class="cl">- 大多數操作只需更新區域計數（無鎖）
</span></span><span class="line"><span class="ln">16</span><span class="cl">- 只有跨執行緒參考才需要更新共享計數</span></span></code></pre></div><h3 id="延遲參考計數">延遲參考計數</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># Free-threading 中的優化策略</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="c1"># 對於不朽物件（immortal objects）</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="c1"># 如 None、True、False、小整數</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="c1"># 完全跳過參考計數</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="c1"># 對於局部物件</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="c1"># 使用區域計數，無需同步</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="c1"># 只有跨執行緒共享的物件</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="c1"># 才需要使用原子操作</span></span></span></code></pre></div><h3 id="記憶體模型變化">記憶體模型變化</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">傳統 CPython（有 GIL）：
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">┌──────────────────────────────────────────┐
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">│  Thread 1  │  Thread 2  │  Thread 3      │
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">│     ↓            ↓            ↓          │
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">│     └────────────┼────────────┘          │
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">│                  ↓                       │
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">│               [ GIL ]                    │
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">│                  ↓                       │
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">│        [ Python Interpreter ]            │
</span></span><span class="line"><span class="ln">10</span><span class="cl">│                  ↓                       │
</span></span><span class="line"><span class="ln">11</span><span class="cl">│          [ 共享記憶體 ]                  │
</span></span><span class="line"><span class="ln">12</span><span class="cl">└──────────────────────────────────────────┘
</span></span><span class="line"><span class="ln">13</span><span class="cl">
</span></span><span class="line"><span class="ln">14</span><span class="cl">Free-threaded CPython：
</span></span><span class="line"><span class="ln">15</span><span class="cl">┌──────────────────────────────────────────┐
</span></span><span class="line"><span class="ln">16</span><span class="cl">│  Thread 1  │  Thread 2  │  Thread 3      │
</span></span><span class="line"><span class="ln">17</span><span class="cl">│     ↓            ↓            ↓          │
</span></span><span class="line"><span class="ln">18</span><span class="cl">│  [Local]     [Local]     [Local]         │
</span></span><span class="line"><span class="ln">19</span><span class="cl">│  State       State       State           │
</span></span><span class="line"><span class="ln">20</span><span class="cl">│     ↓            ↓            ↓          │
</span></span><span class="line"><span class="ln">21</span><span class="cl">│     └────────────┼────────────┘          │
</span></span><span class="line"><span class="ln">22</span><span class="cl">│                  ↓                       │
</span></span><span class="line"><span class="ln">23</span><span class="cl">│     [ 原子操作 / 鎖 / 無鎖資料結構 ]     │
</span></span><span class="line"><span class="ln">24</span><span class="cl">│                  ↓                       │
</span></span><span class="line"><span class="ln">25</span><span class="cl">│          [ 共享記憶體 ]                  │
</span></span><span class="line"><span class="ln">26</span><span class="cl">└──────────────────────────────────────────┘</span></span></code></pre></div><hr>
<h2 id="實戰free-threading-程式設計">【實戰】Free-threading 程式設計</h2>
<h3 id="檢查執行環境">檢查執行環境</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">import</span> <span class="nn">sys</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="k">def</span> <span class="nf">check_environment</span><span class="p">():</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">    <span class="s2">&#34;&#34;&#34;檢查 Free-threading 環境&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="k">try</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">        <span class="n">gil_enabled</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">_is_gil_enabled</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;GIL 啟用: </span><span class="si">{</span><span class="n">gil_enabled</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">        <span class="k">return</span> <span class="ow">not</span> <span class="n">gil_enabled</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    <span class="k">except</span> <span class="ne">AttributeError</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;傳統 Python（有 GIL）&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">        <span class="k">return</span> <span class="kc">False</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="n">is_free_threaded</span> <span class="o">=</span> <span class="n">check_environment</span><span class="p">()</span></span></span></code></pre></div><h3 id="執行緒安全的程式設計">執行緒安全的程式設計</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">import</span> <span class="nn">threading</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="c1"># 不安全：共享可變狀態</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="n">counter</span> <span class="o">=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="k">def</span> <span class="nf">unsafe_increment</span><span class="p">():</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">    <span class="k">global</span> <span class="n">counter</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">    <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">100000</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">        <span class="n">counter</span> <span class="o">+=</span> <span class="mi">1</span>  <span class="c1"># 競爭條件！</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="c1"># 安全：使用鎖</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="n">counter</span> <span class="o">=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="n">lock</span> <span class="o">=</span> <span class="n">threading</span><span class="o">.</span><span class="n">Lock</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">
</span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="k">def</span> <span class="nf">safe_increment</span><span class="p">():</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">    <span class="k">global</span> <span class="n">counter</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">    <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">100000</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">        <span class="k">with</span> <span class="n">lock</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">            <span class="n">counter</span> <span class="o">+=</span> <span class="mi">1</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">
</span></span><span class="line"><span class="ln">21</span><span class="cl"><span class="c1"># 更好：使用原子操作或不可變資料</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl"><span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">Counter</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl"><span class="kn">from</span> <span class="nn">concurrent.futures</span> <span class="kn">import</span> <span class="n">ThreadPoolExecutor</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">
</span></span><span class="line"><span class="ln">25</span><span class="cl"><span class="k">def</span> <span class="nf">better_approach</span><span class="p">(</span><span class="n">data_chunk</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl">    <span class="s2">&#34;&#34;&#34;每個執行緒處理自己的資料，最後合併&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">    <span class="n">local_count</span> <span class="o">=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl">    <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">data_chunk</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">29</span><span class="cl">        <span class="n">local_count</span> <span class="o">+=</span> <span class="n">process</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl">    <span class="k">return</span> <span class="n">local_count</span>
</span></span><span class="line"><span class="ln">31</span><span class="cl">
</span></span><span class="line"><span class="ln">32</span><span class="cl"><span class="k">with</span> <span class="n">ThreadPoolExecutor</span><span class="p">()</span> <span class="k">as</span> <span class="n">executor</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">33</span><span class="cl">    <span class="n">results</span> <span class="o">=</span> <span class="n">executor</span><span class="o">.</span><span class="n">map</span><span class="p">(</span><span class="n">better_approach</span><span class="p">,</span> <span class="n">data_chunks</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">34</span><span class="cl">    <span class="n">total</span> <span class="o">=</span> <span class="nb">sum</span><span class="p">(</span><span class="n">results</span><span class="p">)</span></span></span></code></pre></div><h3 id="適應性程式碼">適應性程式碼</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">import</span> <span class="nn">sys</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="k">def</span> <span class="nf">compute</span><span class="p">(</span><span class="n">data</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">    <span class="s2">&#34;&#34;&#34;根據環境選擇策略&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="n">free_threaded</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">sys</span><span class="p">,</span> <span class="s1">&#39;_is_gil_enabled&#39;</span><span class="p">,</span> <span class="k">lambda</span><span class="p">:</span> <span class="kc">True</span><span class="p">)()</span> <span class="o">==</span> <span class="kc">False</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">    <span class="k">if</span> <span class="n">free_threaded</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">        <span class="c1"># 可以安全使用多執行緒</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">        <span class="k">return</span> <span class="n">parallel_compute_threading</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">        <span class="c1"># 使用多進程或保持單執行緒</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">        <span class="k">return</span> <span class="n">parallel_compute_multiprocess</span><span class="p">(</span><span class="n">data</span><span class="p">)</span></span></span></code></pre></div><hr>
<h2 id="選擇指南並行策略">【選擇指南】並行策略</h2>
<h3 id="決策流程">決策流程</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">你的任務是什麼類型？
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">│
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">├── I/O 密集（網路、檔案、資料庫）
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">│   └── 使用 threading 或 asyncio
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">│       （GIL 不影響）
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">│
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">└── CPU 密集（計算、處理）
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">    │
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    ├── 使用 Free-threaded Python (3.13+)?
</span></span><span class="line"><span class="ln">10</span><span class="cl">    │   ├── 是 → 可以使用 threading
</span></span><span class="line"><span class="ln">11</span><span class="cl">    │   └── 否 → 選擇以下方案
</span></span><span class="line"><span class="ln">12</span><span class="cl">    │
</span></span><span class="line"><span class="ln">13</span><span class="cl">    ├── 可以用 C 擴展？
</span></span><span class="line"><span class="ln">14</span><span class="cl">    │   └── NumPy、Cython 等（會釋放 GIL）
</span></span><span class="line"><span class="ln">15</span><span class="cl">    │
</span></span><span class="line"><span class="ln">16</span><span class="cl">    └── 純 Python？
</span></span><span class="line"><span class="ln">17</span><span class="cl">        └── 使用 multiprocessing 或 ProcessPoolExecutor</span></span></code></pre></div><h3 id="效能比較總結">效能比較總結</h3>
<table>
  <thead>
      <tr>
          <th>任務類型</th>
          <th>threading (有 GIL)</th>
          <th>threading (Free)</th>
          <th>multiprocessing</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>I/O 密集</td>
          <td>好</td>
          <td>好</td>
          <td>過重</td>
      </tr>
      <tr>
          <td>CPU 密集</td>
          <td>無效</td>
          <td>好</td>
          <td>好</td>
      </tr>
      <tr>
          <td>記憶體共享</td>
          <td>簡單</td>
          <td>簡單</td>
          <td>複雜</td>
      </tr>
      <tr>
          <td>啟動成本</td>
          <td>低</td>
          <td>低</td>
          <td>高</td>
      </tr>
  </tbody>
</table>
<hr>
<h2 id="未來gil-的發展">【未來】GIL 的發展</h2>
<h3 id="路線圖">路線圖</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">Python 3.13 (2024): 實驗性 Free-threading
</span></span><span class="line"><span class="ln">2</span><span class="cl">Python 3.14 (2025): 正式支援 Free-threading
</span></span><span class="line"><span class="ln">3</span><span class="cl">Python 3.15/3.16:   可能成為預設
</span></span><span class="line"><span class="ln">4</span><span class="cl">未來:               GIL 可能完全移除</span></span></code></pre></div><h3 id="生態系統遷移">生態系統遷移</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 檢查套件是否支援 Free-threading</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"># pip index versions package-name</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># 主要框架的支援狀態（2025年底）</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="c1"># NumPy 2.1+:       支援</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="c1"># pandas 2.2+:      支援</span>
</span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="c1"># scikit-learn 1.6+: 支援</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="c1"># PyTorch 2.6+:     支援</span></span></span></code></pre></div><hr>
<h2 id="思考題">思考題</h2>
<ol>
<li>如果沒有 GIL，CPython 需要做哪些改變來保證記憶體安全？</li>
<li>為什麼其他 Python 實現（如 Jython、IronPython）沒有 GIL？</li>
<li>Free-threading 的效能損失主要來自哪裡？如何最小化？</li>
</ol>
<h2 id="實作練習">實作練習</h2>
<ol>
<li>寫一個程式，測量 GIL 切換間隔對效能的影響</li>
<li>比較 Free-threaded 和傳統 Python 在相同 CPU 密集任務上的效能</li>
<li>將一個使用 multiprocessing 的程式改寫為 Free-threading 版本</li>
</ol>
<h2 id="延伸閱讀">延伸閱讀</h2>
<ul>
<li><a href="https://peps.python.org/pep-0703/">PEP 703 - Making the Global Interpreter Lock Optional</a></li>
<li><a href="https://py-free-threading.github.io/">Python Free-Threading Guide</a></li>
<li><a href="https://www.dabeaz.com/python/UnderstandingGIL.pdf">Understanding the Python GIL - David Beazley</a></li>
</ul>
<hr>
<p><em>上一章：<a href="/blog/python-advanced/04-cpython-internals/bytecode/" data-link-title="3.3 Bytecode 與虛擬機" data-link-desc="理解 Python 的執行過程">Bytecode 與虛擬機</a></em>
<em>下一模組：<a href="/blog/python-advanced/05-c-extensions/" data-link-title="模組五：用 C 擴展 Python" data-link-desc="學習使用 ctypes、cffi、Cython、pybind11 擴展 Python">模組四：用 C 擴展 Python</a></em></p>
]]></content:encoded></item><item><title>模組五：平台適配</title><link>https://tarrragon.github.io/blog/monitoring/05-platform-adaptation/</link><pubDate>Fri, 19 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/monitoring/05-platform-adaptation/</guid><description>&lt;p>回答「各平台有什麼特殊考量」。&lt;/p>
&lt;h2 id="待寫章節">待寫章節&lt;/h2>
&lt;ul>
&lt;li>&lt;input checked="" disabled="" type="checkbox"> JS/TS 平台：CORS 限制、Service Worker 攔截、SPA 路由變換偵測&lt;/li>
&lt;li>&lt;input checked="" disabled="" type="checkbox"> Flutter 平台：isolate 安全、Platform channel 攔截、app lifecycle&lt;/li>
&lt;li>&lt;input checked="" disabled="" type="checkbox"> Python 平台：GIL 與 threading、atexit 可靠性、subprocess 監控&lt;/li>
&lt;li>&lt;input checked="" disabled="" type="checkbox"> Go 平台：graceful shutdown、signal handling、HTTP server 自身監控&lt;/li>
&lt;li>&lt;input checked="" disabled="" type="checkbox"> 跨平台 timestamp 一致性（時區、精度、clock drift）&lt;/li>
&lt;/ul>
&lt;h2 id="跨分類引用">跨分類引用&lt;/h2>
&lt;ul>
&lt;li>→ &lt;a href="https://tarrragon.github.io/blog/testing/05-test-design-judgment/" data-link-title="模組五：測試設計判斷" data-link-desc="Mock 邊界判斷、assertion 設計、test data 代表性、flaky test 診斷">testing 模組五 測試設計判斷&lt;/a>：各平台 error 攔截差異影響 test 設計&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>回答「各平台有什麼特殊考量」。</p>
<h2 id="待寫章節">待寫章節</h2>
<ul>
<li><input checked="" disabled="" type="checkbox"> JS/TS 平台：CORS 限制、Service Worker 攔截、SPA 路由變換偵測</li>
<li><input checked="" disabled="" type="checkbox"> Flutter 平台：isolate 安全、Platform channel 攔截、app lifecycle</li>
<li><input checked="" disabled="" type="checkbox"> Python 平台：GIL 與 threading、atexit 可靠性、subprocess 監控</li>
<li><input checked="" disabled="" type="checkbox"> Go 平台：graceful shutdown、signal handling、HTTP server 自身監控</li>
<li><input checked="" disabled="" type="checkbox"> 跨平台 timestamp 一致性（時區、精度、clock drift）</li>
</ul>
<h2 id="跨分類引用">跨分類引用</h2>
<ul>
<li>→ <a href="/blog/testing/05-test-design-judgment/" data-link-title="模組五：測試設計判斷" data-link-desc="Mock 邊界判斷、assertion 設計、test data 代表性、flaky test 診斷">testing 模組五 測試設計判斷</a>：各平台 error 攔截差異影響 test 設計</li>
</ul>
]]></content:encoded></item><item><title>4.5 Free-Threading - Python 的真正多執行緒時代</title><link>https://tarrragon.github.io/blog/python-advanced/04-cpython-internals/free-threading/</link><pubDate>Tue, 20 Jan 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/python-advanced/04-cpython-internals/free-threading/</guid><description>&lt;p>Python 3.13 開始提供實驗性的 Free-threading 支援，Python 3.14 正式將其升級為官方支援功能。這是 Python 歷史上最重要的並行處理改進之一。&lt;/p>
&lt;h2 id="什麼是-free-threading">什麼是 Free-Threading？&lt;/h2>
&lt;h3 id="gil-的歷史與限制">GIL 的歷史與限制&lt;/h3>
&lt;p>長久以來，CPython 使用 GIL（Global Interpreter Lock）來簡化記憶體管理和 C 擴展的開發。但這也意味著：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">傳統 Python（有 GIL）：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">┌─────────────────────────────────┐
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">│ Thread 1 → 執行中 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">│ Thread 2 → 等待 GIL... │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">│ Thread 3 → 等待 GIL... │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">│ Thread 4 → 等待 GIL... │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">└─────────────────────────────────┘
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl"> 同一時間只有一個執行緒能執行 Python 程式碼&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>




&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">Free-threaded Python（無 GIL）：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">┌─────────────────────────────────┐
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">│ Thread 1 → 執行中 (Core 1) │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">│ Thread 2 → 執行中 (Core 2) │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">│ Thread 3 → 執行中 (Core 3) │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">│ Thread 4 → 執行中 (Core 4) │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">└─────────────────────────────────┘
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl"> 多個執行緒可以真正並行執行&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="發展歷程">發展歷程&lt;/h3>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>版本&lt;/th>
 &lt;th>狀態&lt;/th>
 &lt;th>PEP&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Python 3.13&lt;/td>
 &lt;td>實驗性支援&lt;/td>
 &lt;td>PEP 703&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Python 3.14&lt;/td>
 &lt;td>正式支援&lt;/td>
 &lt;td>PEP 779&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Python 3.15/3.16&lt;/td>
 &lt;td>可能成為預設&lt;/td>
 &lt;td>待定&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="安裝與啟用">安裝與啟用&lt;/h2>
&lt;h3 id="各平台安裝方式">各平台安裝方式&lt;/h3>
&lt;h4 id="windows--macos">Windows / macOS&lt;/h4>
&lt;p>從 &lt;a href="https://www.python.org/downloads/">python.org&lt;/a> 下載安裝程式，選擇「Customize installation」，勾選「Free threaded mode」。&lt;/p>
&lt;h4 id="ubuntu--debian">Ubuntu / Debian&lt;/h4>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 使用 deadsnakes PPA&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">sudo add-apt-repository ppa:deadsnakes/ppa
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">sudo apt update
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">sudo apt install python3.13-nogil
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">&lt;span class="c1"># 或&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">sudo apt install python3.14-nogil&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>安裝後可使用 &lt;code>python3.13t&lt;/code> 或 &lt;code>python3.14t&lt;/code> 執行。&lt;/p>
&lt;h4 id="從原始碼編譯">從原始碼編譯&lt;/h4>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">./configure --disable-gil
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">make -j&lt;span class="k">$(&lt;/span>nproc&lt;span class="k">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">sudo make install&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="確認安裝">確認安裝&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 檢查版本資訊&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">python3.14t -VV
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">&lt;span class="c1"># 輸出應包含 &amp;#34;free-threading build&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">&lt;span class="c1"># 確認 GIL 狀態&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">python3.14t -c &lt;span class="s2">&amp;#34;import sys; print(&amp;#39;GIL enabled:&amp;#39;, sys._is_gil_enabled())&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">&lt;span class="c1"># 應該輸出：GIL enabled: False&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="控制-gil-狀態">控制 GIL 狀態&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 強制停用 GIL（即使有不相容模組）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">&lt;span class="nv">PYTHON_GIL&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="m">0&lt;/span> python3.14t script.py
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">&lt;span class="c1"># 或使用命令列參數&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">python3.14t -Xgil&lt;span class="o">=&lt;/span>&lt;span class="m">0&lt;/span> script.py
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">&lt;span class="c1"># 強制啟用 GIL（在 free-threaded 版本中）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl">python3.14t -Xgil&lt;span class="o">=&lt;/span>&lt;span class="m">1&lt;/span> script.py&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="效能實測數據">效能實測數據&lt;/h2>
&lt;p>以下數據來自多個可信來源（Real Python、CodSpeed、Facebook Benchmarking）：&lt;/p></description><content:encoded><![CDATA[<p>Python 3.13 開始提供實驗性的 Free-threading 支援，Python 3.14 正式將其升級為官方支援功能。這是 Python 歷史上最重要的並行處理改進之一。</p>
<h2 id="什麼是-free-threading">什麼是 Free-Threading？</h2>
<h3 id="gil-的歷史與限制">GIL 的歷史與限制</h3>
<p>長久以來，CPython 使用 GIL（Global Interpreter Lock）來簡化記憶體管理和 C 擴展的開發。但這也意味著：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">傳統 Python（有 GIL）：
</span></span><span class="line"><span class="ln">2</span><span class="cl">┌─────────────────────────────────┐
</span></span><span class="line"><span class="ln">3</span><span class="cl">│  Thread 1  →  執行中             │
</span></span><span class="line"><span class="ln">4</span><span class="cl">│  Thread 2  →  等待 GIL...        │
</span></span><span class="line"><span class="ln">5</span><span class="cl">│  Thread 3  →  等待 GIL...        │
</span></span><span class="line"><span class="ln">6</span><span class="cl">│  Thread 4  →  等待 GIL...        │
</span></span><span class="line"><span class="ln">7</span><span class="cl">└─────────────────────────────────┘
</span></span><span class="line"><span class="ln">8</span><span class="cl">   同一時間只有一個執行緒能執行 Python 程式碼</span></span></code></pre></div>




<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">Free-threaded Python（無 GIL）：
</span></span><span class="line"><span class="ln">2</span><span class="cl">┌─────────────────────────────────┐
</span></span><span class="line"><span class="ln">3</span><span class="cl">│  Thread 1  →  執行中  (Core 1)   │
</span></span><span class="line"><span class="ln">4</span><span class="cl">│  Thread 2  →  執行中  (Core 2)   │
</span></span><span class="line"><span class="ln">5</span><span class="cl">│  Thread 3  →  執行中  (Core 3)   │
</span></span><span class="line"><span class="ln">6</span><span class="cl">│  Thread 4  →  執行中  (Core 4)   │
</span></span><span class="line"><span class="ln">7</span><span class="cl">└─────────────────────────────────┘
</span></span><span class="line"><span class="ln">8</span><span class="cl">   多個執行緒可以真正並行執行</span></span></code></pre></div><h3 id="發展歷程">發展歷程</h3>
<table>
  <thead>
      <tr>
          <th>版本</th>
          <th>狀態</th>
          <th>PEP</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Python 3.13</td>
          <td>實驗性支援</td>
          <td>PEP 703</td>
      </tr>
      <tr>
          <td>Python 3.14</td>
          <td>正式支援</td>
          <td>PEP 779</td>
      </tr>
      <tr>
          <td>Python 3.15/3.16</td>
          <td>可能成為預設</td>
          <td>待定</td>
      </tr>
  </tbody>
</table>
<h2 id="安裝與啟用">安裝與啟用</h2>
<h3 id="各平台安裝方式">各平台安裝方式</h3>
<h4 id="windows--macos">Windows / macOS</h4>
<p>從 <a href="https://www.python.org/downloads/">python.org</a> 下載安裝程式，選擇「Customize installation」，勾選「Free threaded mode」。</p>
<h4 id="ubuntu--debian">Ubuntu / Debian</h4>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 使用 deadsnakes PPA</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">sudo add-apt-repository ppa:deadsnakes/ppa
</span></span><span class="line"><span class="ln">3</span><span class="cl">sudo apt update
</span></span><span class="line"><span class="ln">4</span><span class="cl">sudo apt install python3.13-nogil
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="c1"># 或</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl">sudo apt install python3.14-nogil</span></span></code></pre></div><p>安裝後可使用 <code>python3.13t</code> 或 <code>python3.14t</code> 執行。</p>
<h4 id="從原始碼編譯">從原始碼編譯</h4>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">./configure --disable-gil
</span></span><span class="line"><span class="ln">2</span><span class="cl">make -j<span class="k">$(</span>nproc<span class="k">)</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">sudo make install</span></span></code></pre></div><h3 id="確認安裝">確認安裝</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 檢查版本資訊</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">python3.14t -VV
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="c1"># 輸出應包含 &#34;free-threading build&#34;</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="c1"># 確認 GIL 狀態</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl">python3.14t -c <span class="s2">&#34;import sys; print(&#39;GIL enabled:&#39;, sys._is_gil_enabled())&#34;</span>
</span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="c1"># 應該輸出：GIL enabled: False</span></span></span></code></pre></div><h3 id="控制-gil-狀態">控制 GIL 狀態</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 強制停用 GIL（即使有不相容模組）</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="nv">PYTHON_GIL</span><span class="o">=</span><span class="m">0</span> python3.14t script.py
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># 或使用命令列參數</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">python3.14t -Xgil<span class="o">=</span><span class="m">0</span> script.py
</span></span><span class="line"><span class="ln">6</span><span class="cl">
</span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="c1"># 強制啟用 GIL（在 free-threaded 版本中）</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl">python3.14t -Xgil<span class="o">=</span><span class="m">1</span> script.py</span></span></code></pre></div><h2 id="效能實測數據">效能實測數據</h2>
<p>以下數據來自多個可信來源（Real Python、CodSpeed、Facebook Benchmarking）：</p>
<h3 id="單執行緒-vs-多執行緒效能">單執行緒 vs 多執行緒效能</h3>
<table>
  <thead>
      <tr>
          <th>場景</th>
          <th>傳統 Python</th>
          <th>Free-threaded</th>
          <th>差異</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>單執行緒</td>
          <td>1.44s</td>
          <td>1.86s</td>
          <td>慢 ~30% (3.13)</td>
      </tr>
      <tr>
          <td>單執行緒</td>
          <td>基準</td>
          <td>慢 ~9%</td>
          <td>(3.14 改善)</td>
      </tr>
      <tr>
          <td>多執行緒 4 核</td>
          <td>1.37s</td>
          <td>0.39s</td>
          <td><strong>快 3.5x</strong></td>
      </tr>
      <tr>
          <td>Fibonacci 並行</td>
          <td>1377ms</td>
          <td>279ms</td>
          <td><strong>快 ~5x</strong></td>
      </tr>
  </tbody>
</table>
<h3 id="關鍵數據">關鍵數據</h3>
<ul>
<li><strong>Python 3.13 單執行緒額外負擔</strong>：約 40%</li>
<li><strong>Python 3.14 單執行緒額外負擔</strong>：約 5-10%（大幅改善）</li>
<li><strong>多執行緒加速比</strong>：接近線性擴展（視任務而定）</li>
</ul>
<blockquote>
<p><strong>重點</strong>：Free-threading 在單執行緒下有效能損失，但在多執行緒 CPU 密集任務中可獲得顯著加速。</p></blockquote>
<h2 id="適用場景判斷">適用場景判斷</h2>
<h3 id="適合使用-free-threading">適合使用 Free-threading</h3>
<ul>
<li><strong>CPU 密集的並行計算</strong>：數學運算、資料處理</li>
<li><strong>可分割的獨立任務</strong>：批次處理、平行搜尋</li>
<li><strong>資料科學工作流程</strong>：大規模資料轉換</li>
<li><strong>科學計算</strong>：模擬、數值分析</li>
</ul>
<h3 id="不適合使用-free-threading">不適合使用 Free-threading</h3>
<ul>
<li><strong>單執行緒應用</strong>：會有 5-10% 效能損失</li>
<li><strong>I/O 密集任務</strong>：傳統 threading 已經足夠</li>
<li><strong>大量使用尚未支援的 C 擴展</strong>：可能導致 GIL 被重新啟用</li>
<li><strong>需要穩定性的生產環境</strong>：生態系統仍在成熟中</li>
</ul>
<h2 id="實際範例">實際範例</h2>
<h3 id="範例-1檢查是否在-free-threaded-模式">範例 1：檢查是否在 Free-threaded 模式</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">import</span> <span class="nn">sys</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="k">def</span> <span class="nf">is_free_threaded</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="nb">bool</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">    <span class="s2">&#34;&#34;&#34;檢查是否在 free-threaded 模式執行&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="k">try</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">        <span class="k">return</span> <span class="ow">not</span> <span class="n">sys</span><span class="o">.</span><span class="n">_is_gil_enabled</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">    <span class="k">except</span> <span class="ne">AttributeError</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">        <span class="c1"># Python 3.12 或更早版本沒有這個函式</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">        <span class="k">return</span> <span class="kc">False</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="k">def</span> <span class="nf">get_python_build_info</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="nb">dict</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">    <span class="s2">&#34;&#34;&#34;取得 Python 建置資訊&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">    <span class="k">return</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">        <span class="s2">&#34;version&#34;</span><span class="p">:</span> <span class="n">sys</span><span class="o">.</span><span class="n">version</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">        <span class="s2">&#34;free_threaded&#34;</span><span class="p">:</span> <span class="n">is_free_threaded</span><span class="p">(),</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">        <span class="s2">&#34;gil_enabled&#34;</span><span class="p">:</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">sys</span><span class="p">,</span> <span class="s1">&#39;_is_gil_enabled&#39;</span><span class="p">,</span> <span class="k">lambda</span><span class="p">:</span> <span class="kc">True</span><span class="p">)(),</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">
</span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&#34;__main__&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">    <span class="n">info</span> <span class="o">=</span> <span class="n">get_python_build_info</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Python 版本: </span><span class="si">{</span><span class="n">info</span><span class="p">[</span><span class="s1">&#39;version&#39;</span><span class="p">]</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Free-threaded: </span><span class="si">{</span><span class="n">info</span><span class="p">[</span><span class="s1">&#39;free_threaded&#39;</span><span class="p">]</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;GIL 啟用: </span><span class="si">{</span><span class="n">info</span><span class="p">[</span><span class="s1">&#39;gil_enabled&#39;</span><span class="p">]</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span></span></span></code></pre></div><h3 id="範例-2並行-cpu-計算">範例 2：並行 CPU 計算</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">import</span> <span class="nn">threading</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="kn">import</span> <span class="nn">time</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="kn">import</span> <span class="nn">sys</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="k">def</span> <span class="nf">cpu_intensive</span><span class="p">(</span><span class="n">n</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">    <span class="s2">&#34;&#34;&#34;CPU 密集計算：計算平方和&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">    <span class="k">return</span> <span class="nb">sum</span><span class="p">(</span><span class="n">i</span> <span class="o">*</span> <span class="n">i</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">n</span><span class="p">))</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="k">def</span> <span class="nf">sequential_compute</span><span class="p">(</span><span class="n">numbers</span><span class="p">:</span> <span class="nb">list</span><span class="p">[</span><span class="nb">int</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="nb">list</span><span class="p">[</span><span class="nb">int</span><span class="p">]:</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="s2">&#34;&#34;&#34;序列計算&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">    <span class="k">return</span> <span class="p">[</span><span class="n">cpu_intensive</span><span class="p">(</span><span class="n">n</span><span class="p">)</span> <span class="k">for</span> <span class="n">n</span> <span class="ow">in</span> <span class="n">numbers</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="k">def</span> <span class="nf">parallel_compute</span><span class="p">(</span><span class="n">numbers</span><span class="p">:</span> <span class="nb">list</span><span class="p">[</span><span class="nb">int</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="nb">list</span><span class="p">[</span><span class="nb">int</span><span class="p">]:</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">    <span class="s2">&#34;&#34;&#34;並行計算&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">    <span class="n">results</span> <span class="o">=</span> <span class="p">[</span><span class="kc">None</span><span class="p">]</span> <span class="o">*</span> <span class="nb">len</span><span class="p">(</span><span class="n">numbers</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">
</span></span><span class="line"><span class="ln">17</span><span class="cl">    <span class="k">def</span> <span class="nf">worker</span><span class="p">(</span><span class="n">idx</span><span class="p">:</span> <span class="nb">int</span><span class="p">,</span> <span class="n">n</span><span class="p">:</span> <span class="nb">int</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">        <span class="n">results</span><span class="p">[</span><span class="n">idx</span><span class="p">]</span> <span class="o">=</span> <span class="n">cpu_intensive</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">
</span></span><span class="line"><span class="ln">20</span><span class="cl">    <span class="n">threads</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">        <span class="n">threading</span><span class="o">.</span><span class="n">Thread</span><span class="p">(</span><span class="n">target</span><span class="o">=</span><span class="n">worker</span><span class="p">,</span> <span class="n">args</span><span class="o">=</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">n</span><span class="p">))</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">        <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">n</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">numbers</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">    <span class="p">]</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">
</span></span><span class="line"><span class="ln">25</span><span class="cl">    <span class="k">for</span> <span class="n">t</span> <span class="ow">in</span> <span class="n">threads</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl">        <span class="n">t</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">    <span class="k">for</span> <span class="n">t</span> <span class="ow">in</span> <span class="n">threads</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl">        <span class="n">t</span><span class="o">.</span><span class="n">join</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">29</span><span class="cl">
</span></span><span class="line"><span class="ln">30</span><span class="cl">    <span class="k">return</span> <span class="n">results</span>
</span></span><span class="line"><span class="ln">31</span><span class="cl">
</span></span><span class="line"><span class="ln">32</span><span class="cl"><span class="k">def</span> <span class="nf">benchmark</span><span class="p">():</span>
</span></span><span class="line"><span class="ln">33</span><span class="cl">    <span class="s2">&#34;&#34;&#34;效能比較&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">34</span><span class="cl">    <span class="n">numbers</span> <span class="o">=</span> <span class="p">[</span><span class="mi">5_000_000</span><span class="p">]</span> <span class="o">*</span> <span class="mi">4</span>
</span></span><span class="line"><span class="ln">35</span><span class="cl">
</span></span><span class="line"><span class="ln">36</span><span class="cl">    <span class="c1"># 序列執行</span>
</span></span><span class="line"><span class="ln">37</span><span class="cl">    <span class="n">start</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">perf_counter</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">38</span><span class="cl">    <span class="n">sequential_compute</span><span class="p">(</span><span class="n">numbers</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">39</span><span class="cl">    <span class="n">sequential_time</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">perf_counter</span><span class="p">()</span> <span class="o">-</span> <span class="n">start</span>
</span></span><span class="line"><span class="ln">40</span><span class="cl">
</span></span><span class="line"><span class="ln">41</span><span class="cl">    <span class="c1"># 並行執行</span>
</span></span><span class="line"><span class="ln">42</span><span class="cl">    <span class="n">start</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">perf_counter</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">43</span><span class="cl">    <span class="n">parallel_compute</span><span class="p">(</span><span class="n">numbers</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">44</span><span class="cl">    <span class="n">parallel_time</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">perf_counter</span><span class="p">()</span> <span class="o">-</span> <span class="n">start</span>
</span></span><span class="line"><span class="ln">45</span><span class="cl">
</span></span><span class="line"><span class="ln">46</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;序列執行: </span><span class="si">{</span><span class="n">sequential_time</span><span class="si">:</span><span class="s2">.3f</span><span class="si">}</span><span class="s2">s&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">47</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;並行執行: </span><span class="si">{</span><span class="n">parallel_time</span><span class="si">:</span><span class="s2">.3f</span><span class="si">}</span><span class="s2">s&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">48</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;加速比: </span><span class="si">{</span><span class="n">sequential_time</span> <span class="o">/</span> <span class="n">parallel_time</span><span class="si">:</span><span class="s2">.2f</span><span class="si">}</span><span class="s2">x&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">49</span><span class="cl">
</span></span><span class="line"><span class="ln">50</span><span class="cl">    <span class="c1"># 在傳統 Python 中，加速比接近 1（無改善）</span>
</span></span><span class="line"><span class="ln">51</span><span class="cl">    <span class="c1"># 在 Free-threaded Python 中，加速比接近 CPU 核心數</span>
</span></span><span class="line"><span class="ln">52</span><span class="cl">
</span></span><span class="line"><span class="ln">53</span><span class="cl"><span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&#34;__main__&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">54</span><span class="cl">    <span class="k">try</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">55</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;GIL 啟用: </span><span class="si">{</span><span class="n">sys</span><span class="o">.</span><span class="n">_is_gil_enabled</span><span class="p">()</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">56</span><span class="cl">    <span class="k">except</span> <span class="ne">AttributeError</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">57</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;GIL 狀態: 無法檢測（舊版 Python）&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">58</span><span class="cl">
</span></span><span class="line"><span class="ln">59</span><span class="cl">    <span class="n">benchmark</span><span class="p">()</span></span></span></code></pre></div><h3 id="範例-3使用-threadpoolexecutor">範例 3：使用 ThreadPoolExecutor</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">from</span> <span class="nn">concurrent.futures</span> <span class="kn">import</span> <span class="n">ThreadPoolExecutor</span><span class="p">,</span> <span class="n">as_completed</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="kn">import</span> <span class="nn">time</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="kn">import</span> <span class="nn">sys</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="k">def</span> <span class="nf">process_chunk</span><span class="p">(</span><span class="n">chunk_id</span><span class="p">:</span> <span class="nb">int</span><span class="p">,</span> <span class="n">size</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">dict</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">    <span class="s2">&#34;&#34;&#34;處理一個資料區塊&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">    <span class="n">result</span> <span class="o">=</span> <span class="nb">sum</span><span class="p">(</span><span class="n">i</span> <span class="o">*</span> <span class="n">i</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">size</span><span class="p">))</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">    <span class="k">return</span> <span class="p">{</span><span class="s2">&#34;chunk_id&#34;</span><span class="p">:</span> <span class="n">chunk_id</span><span class="p">,</span> <span class="s2">&#34;result&#34;</span><span class="p">:</span> <span class="n">result</span><span class="p">}</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="k">def</span> <span class="nf">parallel_process</span><span class="p">(</span><span class="n">num_chunks</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">8</span><span class="p">,</span> <span class="n">chunk_size</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">2_000_000</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">    <span class="s2">&#34;&#34;&#34;並行處理多個資料區塊&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">    <span class="n">start</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">perf_counter</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">
</span></span><span class="line"><span class="ln">14</span><span class="cl">    <span class="k">with</span> <span class="n">ThreadPoolExecutor</span><span class="p">(</span><span class="n">max_workers</span><span class="o">=</span><span class="n">num_chunks</span><span class="p">)</span> <span class="k">as</span> <span class="n">executor</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">        <span class="n">futures</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">            <span class="n">executor</span><span class="o">.</span><span class="n">submit</span><span class="p">(</span><span class="n">process_chunk</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">chunk_size</span><span class="p">):</span> <span class="n">i</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">            <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">num_chunks</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">
</span></span><span class="line"><span class="ln">20</span><span class="cl">        <span class="n">results</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">        <span class="k">for</span> <span class="n">future</span> <span class="ow">in</span> <span class="n">as_completed</span><span class="p">(</span><span class="n">futures</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">            <span class="n">chunk_id</span> <span class="o">=</span> <span class="n">futures</span><span class="p">[</span><span class="n">future</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">            <span class="n">result</span> <span class="o">=</span> <span class="n">future</span><span class="o">.</span><span class="n">result</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">            <span class="n">results</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">result</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">            <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Chunk </span><span class="si">{</span><span class="n">chunk_id</span><span class="si">}</span><span class="s2"> 完成&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl">
</span></span><span class="line"><span class="ln">27</span><span class="cl">    <span class="n">elapsed</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">perf_counter</span><span class="p">()</span> <span class="o">-</span> <span class="n">start</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;</span><span class="se">\n</span><span class="s2">總耗時: </span><span class="si">{</span><span class="n">elapsed</span><span class="si">:</span><span class="s2">.3f</span><span class="si">}</span><span class="s2">s&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">29</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;平均每個 chunk: </span><span class="si">{</span><span class="n">elapsed</span> <span class="o">/</span> <span class="n">num_chunks</span><span class="si">:</span><span class="s2">.3f</span><span class="si">}</span><span class="s2">s&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl">
</span></span><span class="line"><span class="ln">31</span><span class="cl">    <span class="k">return</span> <span class="n">results</span>
</span></span><span class="line"><span class="ln">32</span><span class="cl">
</span></span><span class="line"><span class="ln">33</span><span class="cl"><span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&#34;__main__&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">34</span><span class="cl">    <span class="k">try</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">35</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Free-threaded 模式: </span><span class="si">{</span><span class="ow">not</span> <span class="n">sys</span><span class="o">.</span><span class="n">_is_gil_enabled</span><span class="p">()</span><span class="si">}</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">36</span><span class="cl">    <span class="k">except</span> <span class="ne">AttributeError</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">37</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;傳統 Python 模式</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">38</span><span class="cl">
</span></span><span class="line"><span class="ln">39</span><span class="cl">    <span class="n">parallel_process</span><span class="p">()</span></span></span></code></pre></div><h2 id="concurrentinterpreters-模組python-314-新增">concurrent.interpreters 模組（Python 3.14 新增）</h2>
<p>Python 3.14 引入了全新的 <code>concurrent.interpreters</code> 模組，提供了另一種並行方式。</p>
<h3 id="什麼是多解釋器">什麼是多解釋器？</h3>
<p>多解釋器（Multiple Interpreters）是在同一個進程中運行多個獨立的 Python 直譯器：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">┌─────────────────────────────────────────┐
</span></span><span class="line"><span class="ln">2</span><span class="cl">│              單一進程                     │
</span></span><span class="line"><span class="ln">3</span><span class="cl">│  ┌──────────┐  ┌──────────┐             │
</span></span><span class="line"><span class="ln">4</span><span class="cl">│  │ 解釋器 1  │  │ 解釋器 2  │             │
</span></span><span class="line"><span class="ln">5</span><span class="cl">│  │ (獨立)   │  │ (獨立)   │             │
</span></span><span class="line"><span class="ln">6</span><span class="cl">│  │ sys.path │  │ sys.path │  ← 完全隔離  │
</span></span><span class="line"><span class="ln">7</span><span class="cl">│  │ modules  │  │ modules  │             │
</span></span><span class="line"><span class="ln">8</span><span class="cl">│  └──────────┘  └──────────┘             │
</span></span><span class="line"><span class="ln">9</span><span class="cl">└─────────────────────────────────────────┘</span></span></code></pre></div><h3 id="基本用法">基本用法</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">from</span> <span class="nn">concurrent.futures</span> <span class="kn">import</span> <span class="n">InterpreterPoolExecutor</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="k">def</span> <span class="nf">cpu_task</span><span class="p">(</span><span class="n">n</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">    <span class="s2">&#34;&#34;&#34;在獨立解釋器中執行的任務&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="k">return</span> <span class="nb">sum</span><span class="p">(</span><span class="n">i</span> <span class="o">*</span> <span class="n">i</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">n</span><span class="p">))</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&#34;__main__&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">    <span class="n">numbers</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1_000_000</span><span class="p">,</span> <span class="mi">2_000_000</span><span class="p">,</span> <span class="mi">3_000_000</span><span class="p">,</span> <span class="mi">4_000_000</span><span class="p">]</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="c1"># 使用多解釋器池</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">    <span class="k">with</span> <span class="n">InterpreterPoolExecutor</span><span class="p">(</span><span class="n">max_workers</span><span class="o">=</span><span class="mi">4</span><span class="p">)</span> <span class="k">as</span> <span class="n">executor</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">        <span class="n">results</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">executor</span><span class="o">.</span><span class="n">map</span><span class="p">(</span><span class="n">cpu_task</span><span class="p">,</span> <span class="n">numbers</span><span class="p">))</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">
</span></span><span class="line"><span class="ln">14</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;結果: </span><span class="si">{</span><span class="n">results</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span></span></span></code></pre></div><h3 id="多解釋器-vs-多進程-vs-多執行緒">多解釋器 vs 多進程 vs 多執行緒</h3>
<table>
  <thead>
      <tr>
          <th>特性</th>
          <th>threading</th>
          <th>multiprocessing</th>
          <th>interpreters</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>隔離程度</td>
          <td>共享記憶體</td>
          <td>完全隔離</td>
          <td>部分隔離</td>
      </tr>
      <tr>
          <td>資源消耗</td>
          <td>最低</td>
          <td>最高</td>
          <td>中等</td>
      </tr>
      <tr>
          <td>啟動速度</td>
          <td>最快</td>
          <td>最慢</td>
          <td>中等</td>
      </tr>
      <tr>
          <td>通訊方式</td>
          <td>直接存取</td>
          <td>pickle/Queue</td>
          <td>pickle</td>
      </tr>
      <tr>
          <td>GIL 影響</td>
          <td>受限（傳統）/ 無（Free-threaded）</td>
          <td>無</td>
          <td>無</td>
      </tr>
  </tbody>
</table>
<h3 id="何時使用多解釋器">何時使用多解釋器</h3>
<ul>
<li>需要隔離但不想付出多進程的代價</li>
<li>想要類似 CSP/Actor 模型的並行方式</li>
<li>需要在同一進程中運行不同配置的 Python 環境</li>
</ul>
<h2 id="已知問題與陷阱">已知問題與陷阱</h2>
<h3 id="來自-github-issues-的真實案例">來自 GitHub Issues 的真實案例</h3>
<p><strong>1. pathlib 的 race condition</strong>（<a href="https://github.com/python/cpython/issues/139001">#139001</a>）</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 在 3.14t 中可能有問題</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="kn">from</span> <span class="nn">pathlib</span> <span class="kn">import</span> <span class="n">Path</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="kn">import</span> <span class="nn">threading</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="n">path</span> <span class="o">=</span> <span class="n">Path</span><span class="p">(</span><span class="s2">&#34;/some/path&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl">
</span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="k">def</span> <span class="nf">check_path</span><span class="p">():</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl">    <span class="c1"># is_dir() 在多執行緒下可能有競爭條件</span>
</span></span><span class="line"><span class="ln">9</span><span class="cl">    <span class="k">return</span> <span class="n">path</span><span class="o">.</span><span class="n">is_dir</span><span class="p">()</span></span></span></code></pre></div><p><strong>2. click 套件的問題</strong>（<a href="https://github.com/python/cpython/issues/136248">#136248</a>）</p>
<p>使用 click 套件時，在 free-threaded 模式下可能出現意外行為。</p>
<p><strong>3. buffer interface 的資料競爭</strong>（<a href="https://github.com/python/cpython/issues/130977">#130977</a>）</p>
<p>使用 memoryview 或其他 buffer interface 時需特別注意。</p>
<h3 id="常見錯誤模式">常見錯誤模式</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># 錯誤：全域狀態未加鎖保護</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="n">cache</span> <span class="o">=</span> <span class="p">{}</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="k">def</span> <span class="nf">get_cached</span><span class="p">(</span><span class="n">key</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="k">if</span> <span class="n">key</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">cache</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">        <span class="n">cache</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="n">expensive_compute</span><span class="p">(</span><span class="n">key</span><span class="p">)</span>  <span class="c1"># 競爭條件！</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">    <span class="k">return</span> <span class="n">cache</span><span class="p">[</span><span class="n">key</span><span class="p">]</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="c1"># 正確：使用 Lock 保護</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="kn">import</span> <span class="nn">threading</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">
</span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="n">cache</span> <span class="o">=</span> <span class="p">{}</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="n">cache_lock</span> <span class="o">=</span> <span class="n">threading</span><span class="o">.</span><span class="n">Lock</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">
</span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="k">def</span> <span class="nf">get_cached_safe</span><span class="p">(</span><span class="n">key</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">    <span class="k">with</span> <span class="n">cache_lock</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">        <span class="k">if</span> <span class="n">key</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">cache</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">            <span class="n">cache</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="n">expensive_compute</span><span class="p">(</span><span class="n">key</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">        <span class="k">return</span> <span class="n">cache</span><span class="p">[</span><span class="n">key</span><span class="p">]</span></span></span></code></pre></div>




<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># 錯誤：依賴內建型別的「隱式」執行緒安全</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="n">results</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="k">def</span> <span class="nf">worker</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="n">result</span> <span class="o">=</span> <span class="n">compute</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">    <span class="n">results</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">result</span><span class="p">)</span>  <span class="c1"># 在 free-threaded 中可能不安全</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="c1"># 正確：返回結果，由主執行緒收集</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="k">def</span> <span class="nf">worker_safe</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="k">return</span> <span class="n">compute</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">
</span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="k">with</span> <span class="n">ThreadPoolExecutor</span><span class="p">()</span> <span class="k">as</span> <span class="n">executor</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">    <span class="n">results</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">executor</span><span class="o">.</span><span class="n">map</span><span class="p">(</span><span class="n">worker_safe</span><span class="p">,</span> <span class="n">items</span><span class="p">))</span></span></span></code></pre></div><h2 id="套件相容性現況2025-年底">套件相容性現況（2025 年底）</h2>
<h3 id="已完全支援">已完全支援</h3>
<table>
  <thead>
      <tr>
          <th>套件</th>
          <th>版本</th>
          <th>備註</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>NumPy</td>
          <td>2.1.0+</td>
          <td>科學計算基礎</td>
      </tr>
      <tr>
          <td>SciPy</td>
          <td>1.15.0+</td>
          <td>科學計算</td>
      </tr>
      <tr>
          <td>pandas</td>
          <td>2.2.3+</td>
          <td>資料分析</td>
      </tr>
      <tr>
          <td>PyTorch</td>
          <td>2.6.0+</td>
          <td>深度學習</td>
      </tr>
      <tr>
          <td>scikit-learn</td>
          <td>1.6.0+</td>
          <td>機器學習</td>
      </tr>
      <tr>
          <td>Pillow</td>
          <td>11.0.0+</td>
          <td>圖像處理</td>
      </tr>
      <tr>
          <td>Matplotlib</td>
          <td>3.9.0+</td>
          <td>繪圖</td>
      </tr>
  </tbody>
</table>
<h3 id="部分支援或開發中">部分支援或開發中</h3>
<ul>
<li>cryptography、h5py、polars</li>
<li>aiohttp、multidict、yarl</li>
<li>多個 aio-libs 套件</li>
</ul>
<h3 id="尚未支援">尚未支援</h3>
<ul>
<li>lxml、cupy 等特定套件</li>
<li>部分 C 擴展模組</li>
</ul>
<blockquote>
<p><strong>追蹤最新狀態</strong>：<a href="https://py-free-threading.github.io/tracking/">py-free-threading.github.io/tracking</a></p></blockquote>
<h2 id="最佳實踐與建議">最佳實踐與建議</h2>
<h3 id="1-漸進式採用">1. 漸進式採用</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">import</span> <span class="nn">sys</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">    <span class="c1"># 檢查執行環境</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="n">free_threaded</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">sys</span><span class="p">,</span> <span class="s1">&#39;_is_gil_enabled&#39;</span><span class="p">,</span> <span class="k">lambda</span><span class="p">:</span> <span class="kc">True</span><span class="p">)()</span> <span class="o">==</span> <span class="kc">False</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">    <span class="k">if</span> <span class="n">free_threaded</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;使用 Free-threaded 最佳化路徑&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">        <span class="n">run_parallel_optimized</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;使用傳統多進程路徑&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">        <span class="n">run_multiprocess_fallback</span><span class="p">()</span></span></span></code></pre></div><h3 id="2-明確使用同步原語">2. 明確使用同步原語</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln">1</span><span class="cl"><span class="kn">import</span> <span class="nn">threading</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="c1"># 永遠明確使用 Lock，不要依賴「可能」的執行緒安全</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="n">lock</span> <span class="o">=</span> <span class="n">threading</span><span class="o">.</span><span class="n">Lock</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">
</span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="k">def</span> <span class="nf">thread_safe_operation</span><span class="p">():</span>
</span></span><span class="line"><span class="ln">7</span><span class="cl">    <span class="k">with</span> <span class="n">lock</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl">        <span class="c1"># 關鍵區段</span>
</span></span><span class="line"><span class="ln">9</span><span class="cl">        <span class="k">pass</span></span></span></code></pre></div><h3 id="3-測試策略">3. 測試策略</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># 使用較短的執行緒切換間隔來暴露潛在的競爭條件</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="kn">import</span> <span class="nn">sys</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="n">sys</span><span class="o">.</span><span class="n">setswitchinterval</span><span class="p">(</span><span class="mf">0.0001</span><span class="p">)</span>  <span class="c1"># 測試時使用</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="c1"># 運行大量並行測試</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="kn">import</span> <span class="nn">concurrent.futures</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="kn">import</span> <span class="nn">random</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="k">def</span> <span class="nf">stress_test</span><span class="p">(</span><span class="n">func</span><span class="p">,</span> <span class="n">iterations</span><span class="o">=</span><span class="mi">1000</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="k">with</span> <span class="n">concurrent</span><span class="o">.</span><span class="n">futures</span><span class="o">.</span><span class="n">ThreadPoolExecutor</span><span class="p">(</span><span class="n">max_workers</span><span class="o">=</span><span class="mi">10</span><span class="p">)</span> <span class="k">as</span> <span class="n">executor</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">        <span class="n">futures</span> <span class="o">=</span> <span class="p">[</span><span class="n">executor</span><span class="o">.</span><span class="n">submit</span><span class="p">(</span><span class="n">func</span><span class="p">)</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">iterations</span><span class="p">)]</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">        <span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">concurrent</span><span class="o">.</span><span class="n">futures</span><span class="o">.</span><span class="n">as_completed</span><span class="p">(</span><span class="n">futures</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">            <span class="n">f</span><span class="o">.</span><span class="n">result</span><span class="p">()</span>  <span class="c1"># 會拋出任何異常</span></span></span></code></pre></div><h3 id="4-檢查依賴套件相容性">4. 檢查依賴套件相容性</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="k">def</span> <span class="nf">check_dependencies</span><span class="p">():</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">    <span class="s2">&#34;&#34;&#34;檢查關鍵依賴是否支援 free-threading&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">    <span class="kn">import</span> <span class="nn">importlib.metadata</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="n">packages_to_check</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;numpy&#39;</span><span class="p">,</span> <span class="s1">&#39;pandas&#39;</span><span class="p">,</span> <span class="s1">&#39;scikit-learn&#39;</span><span class="p">]</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">    <span class="n">results</span> <span class="o">=</span> <span class="p">{}</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">    <span class="k">for</span> <span class="n">pkg</span> <span class="ow">in</span> <span class="n">packages_to_check</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">        <span class="k">try</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">            <span class="n">version</span> <span class="o">=</span> <span class="n">importlib</span><span class="o">.</span><span class="n">metadata</span><span class="o">.</span><span class="n">version</span><span class="p">(</span><span class="n">pkg</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">            <span class="n">results</span><span class="p">[</span><span class="n">pkg</span><span class="p">]</span> <span class="o">=</span> <span class="n">version</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">        <span class="k">except</span> <span class="n">importlib</span><span class="o">.</span><span class="n">metadata</span><span class="o">.</span><span class="n">PackageNotFoundError</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">            <span class="n">results</span><span class="p">[</span><span class="n">pkg</span><span class="p">]</span> <span class="o">=</span> <span class="s2">&#34;未安裝&#34;</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">
</span></span><span class="line"><span class="ln">15</span><span class="cl">    <span class="k">return</span> <span class="n">results</span></span></span></code></pre></div><h2 id="未來展望">未來展望</h2>
<h3 id="路線圖">路線圖</h3>
<ul>
<li><strong>Python 3.15</strong>：預期 Free-threading 將成為可選的預設選項</li>
<li><strong>Python 3.16</strong>：可能成為真正的預設建置</li>
<li><strong>長期</strong>：GIL 可能完全移除</li>
</ul>
<h3 id="社群呼籲">社群呼籲</h3>
<blockquote>
<p>「Free-threaded 建置是這個語言的未來。現階段我們需要更多來自真實工作流程的回饋報告。」
— Quansight Labs</p></blockquote>
<p>如果你正在使用 Free-threaded Python，歡迎：</p>
<ul>
<li>回報問題到 <a href="https://github.com/python/cpython/issues">Python Bug Tracker</a></li>
<li>參與 <a href="https://discord.gg/rqgHCDqdRr">py-free-threading Discord</a> 討論</li>
<li>測試你的套件並提交相容性報告</li>
</ul>
<h2 id="思考題">思考題</h2>
<ol>
<li>為什麼 Free-threading 在單執行緒下會有效能損失？這個損失從 40% 降到 9% 是如何達成的？</li>
<li>什麼情況下應該使用 <code>InterpreterPoolExecutor</code> 而不是 <code>ThreadPoolExecutor</code>？</li>
<li>如果你的程式依賴一個尚未支援 Free-threading 的套件，有什麼替代方案？</li>
</ol>
<h2 id="實作練習">實作練習</h2>
<ol>
<li>寫一個程式，比較在傳統 Python 和 Free-threaded Python 下的多執行緒效能差異</li>
<li>使用 <code>InterpreterPoolExecutor</code> 實作一個簡單的任務佇列系統</li>
<li>為一個現有的單執行緒程式添加 Free-threading 支援，並處理執行緒安全問題</li>
</ol>
<h2 id="延伸閱讀">延伸閱讀</h2>
<ul>
<li><a href="https://docs.python.org/3/howto/free-threading-python.html">Python 3.14 官方文件 - Free Threading</a></li>
<li><a href="https://py-free-threading.github.io/">Python Free-Threading Guide</a></li>
<li><a href="https://peps.python.org/pep-0703/">PEP 703 - Making the Global Interpreter Lock Optional</a></li>
<li><a href="https://peps.python.org/pep-0779/">PEP 779 - Criteria for Supported Status</a></li>
<li><a href="https://labs.quansight.org/blog/free-threaded-one-year-recap">Quansight Labs - Free-Threaded Python 第一年回顧</a></li>
</ul>
<h2 id="相關章節">相關章節</h2>
<ul>
<li><a href="/blog/python-advanced/04-cpython-internals/gil-threading/" data-link-title="3.4 GIL 與執行緒模型" data-link-desc="深入理解 GIL 的設計與實現">GIL 與執行緒模型</a> - 深入理解 GIL 的設計與實現</li>
<li><a href="/blog/python-advanced/05-c-extensions/" data-link-title="模組五：用 C 擴展 Python" data-link-desc="學習使用 ctypes、cffi、Cython、pybind11 擴展 Python">用 C 擴展 Python</a> - 使用 C 擴展繞過 GIL 的傳統方法</li>
<li><a href="/blog/python-advanced/06-rust-extensions/" data-link-title="模組六：用 Rust 擴展 Python" data-link-desc="學習使用 PyO3 和 Maturin 用 Rust 擴展 Python">用 Rust 擴展 Python</a> - 使用 PyO3 建立高效能擴展</li>
</ul>
<h2 id="先備知識">先備知識</h2>
<ul>
<li>入門系列 <a href="/blog/python/03-stdlib/concurrency/" data-link-title="3.7 並行處理 - threading、multiprocessing、concurrent.futures" data-link-desc="Python 並行處理的三種方式與選擇指南">並行處理</a> - threading、multiprocessing 基礎</li>
</ul>
<hr>
<p><em>上一章：<a href="/blog/python-advanced/04-cpython-internals/gil-threading/" data-link-title="3.4 GIL 與執行緒模型" data-link-desc="深入理解 GIL 的設計與實現">GIL 與執行緒模型</a></em>
<em>下一模組：<a href="/blog/python-advanced/05-c-extensions/" data-link-title="模組五：用 C 擴展 Python" data-link-desc="學習使用 ctypes、cffi、Cython、pybind11 擴展 Python">模組五：用 C 擴展 Python</a></em></p>
]]></content:encoded></item></channel></rss>