最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python GIL(全局解釋器鎖)的使用小結(jié)

 更新時間:2025年11月24日 09:21:02   作者:唐古烏梁海  
本文主要介紹了Python GIL(全局解釋器鎖)的使用小結(jié),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

我們通常所說的GIL,指的是全局解釋器鎖(Global Interpreter Lock),是計算機(jī)程序設(shè)計語言解釋器用于同步線程的一種機(jī)制,它使得任何時刻僅有一個線程在執(zhí)行。即使在多核處理器上,使用 GIL 的解釋器也只允許同一時間執(zhí)行一個線程。

在Python中,GIL的存在主要是為了簡化CPython解釋器的實現(xiàn),因為CPython的內(nèi)存管理不是線程安全的。GIL可以防止并發(fā)訪問Python對象,從而避免多個線程同時修改同一個對象導(dǎo)致的數(shù)據(jù)不一致問題。

但是,GIL也導(dǎo)致了一個問題:在多核CPU上,使用多線程的Python程序并不能真正地并行執(zhí)行,而是通過交替執(zhí)行來模擬并發(fā)。因此,對于CPU密集型的任務(wù),使用多線程并不能提高性能,甚至可能因為線程切換的開銷而降低性能。

然而,對于I/O密集型的任務(wù)(如網(wǎng)絡(luò)請求、文件讀寫等),由于線程在等待I/O時會被阻塞,此時GIL會被釋放,從而允許其他線程運行,因此多線程在I/O密集型任務(wù)中仍然可以提升性能。

為了克服GIL的限制,可以采用多進(jìn)程(使用multiprocessing模塊)來利用多核CPU,因為每個進(jìn)程有自己獨立的Python解釋器和內(nèi)存空間,因此每個進(jìn)程都有自己的GIL,從而可以實現(xiàn)真正的并行。

什么是 GIL?

GIL(Global Interpreter Lock) 是 CPython 解釋器中的一個互斥鎖,它確保在任何時刻只有一個線程在執(zhí)行 Python 字節(jié)碼。這意味著即使在多核 CPU 上,CPython 也無法實現(xiàn)真正的并行線程執(zhí)行。

GIL 的工作原理

+-----------------------------------------------+
|              Python 進(jìn)程 (單個進(jìn)程)            |
|                                               |
|  +-----------------------------------------+  |
|  |          全局解釋器鎖 (GIL)              |  |
|  |                                         |  |
|  |      ?? 一把鎖,控制 Python 字節(jié)碼執(zhí)行    |  |
|  +-----------------------------------------+  |
|                    ↑                          |
|                    | (獲取/釋放)              |
|                    |                          |
|  +------------+  +------------+  +------------+|
|  |  線程 1    |  |  線程 2    |  |  線程 3    ||
|  |            |  |            |  |            ||
|  | Python代碼 |  | Python代碼 |  | Python代碼 ||
|  |  執(zhí)行中    |  |  等待中    |  |  等待中    ||
|  +------------+  +------------+  +------------+|
|                                               |
+-----------------------------------------------+

關(guān)鍵點:

  • ?? GIL 是進(jìn)程級別的鎖,不是線程級別的
  • ?? 同一時間只有一個線程能持有 GIL 并執(zhí)行 Python 字節(jié)碼
  • ? 其他線程必須等待 GIL 被釋放
import threading
import time

def count_down(n):
    while n > 0:
        n -= 1

# 單線程執(zhí)行
start = time.time()
count_down(100000000)
single_time = time.time() - start

# 多線程執(zhí)行
start = time.time()
t1 = threading.Thread(target=count_down, args=(50000000,))
t2 = threading.Thread(target=count_down, args=(50000000,))
t1.start()
t2.start()
t1.join()
t2.join()
multi_time = time.time() - start

print(f"單線程執(zhí)行時間: {single_time:.2f}秒")
print(f"雙線程執(zhí)行時間: {multi_time:.2f}秒")
# 你會發(fā)現(xiàn)多線程可能比單線程更慢!

為什么需要 GIL?

1. 簡化內(nèi)存管理

Python 使用引用計數(shù)進(jìn)行內(nèi)存管理:

import sys

a = []
print(sys.getrefcount(a))  # 查看對象的引用計數(shù)

b = a
print(sys.getrefcount(a))  # 引用計數(shù)增加

沒有 GIL 時,多個線程同時修改引用計數(shù)會導(dǎo)致競爭條件:

# 偽代碼演示競爭條件
# 線程1: obj.ref_count += 1
# 線程2: obj.ref_count -= 1
# 如果沒有同步機(jī)制,ref_count 可能出錯

2. 保護(hù)內(nèi)部數(shù)據(jù)結(jié)構(gòu)

Python 的很多內(nèi)部數(shù)據(jù)結(jié)構(gòu)(如 list、dict)不是線程安全的。

GIL 的影響

CPU 密集型任務(wù)

import threading
import time

def cpu_intensive_task():
    result = 0
    for i in range(10**7):
        result += i * i
    return result

# 測試多線程性能
def test_multithreading():
    threads = []
    start_time = time.time()
    
    for _ in range(4):
        t = threading.Thread(target=cpu_intensive_task)
        threads.append(t)
        t.start()
    
    for t in threads:
        t.join()
    
    print(f"多線程執(zhí)行時間: {time.time() - start_time:.2f}秒")

# 對比多進(jìn)程
import multiprocessing

def test_multiprocessing():
    processes = []
    start_time = time.time()
    
    for _ in range(4):
        p = multiprocessing.Process(target=cpu_intensive_task)
        processes.append(p)
        p.start()
    
    for p in processes:
        p.join()
    
    print(f"多進(jìn)程執(zhí)行時間: {time.time() - start_time:.2f}秒")

# 運行測試
if __name__ == "__main__":
    test_multithreading()  # 可能比單線程還慢
    test_multiprocessing()  # 真正的并行,速度更快

I/O 密集型任務(wù)

import threading
import time
import requests

def download_site(url, session):
    with session.get(url) as response:
        print(f"Read {len(response.content)} from {url}")

def download_all_sites(sites):
    with requests.Session() as session:
        # 單線程
        start_time = time.time()
        for url in sites:
            download_site(url, session)
        print(f"單線程下載時間: {time.time() - start_time:.2f}秒")
        
        # 多線程
        start_time = time.time()
        threads = []
        for url in sites:
            thread = threading.Thread(target=download_site, args=(url, session))
            thread.start()
            threads.append(thread)
        
        for thread in threads:
            thread.join()
        print(f"多線程下載時間: {time.time() - start_time:.2f}秒")

# I/O 密集型任務(wù)中,多線程有明顯優(yōu)勢

如何繞過 GIL 的限制

1. 使用多進(jìn)程

from multiprocessing import Pool, cpu_count
import math

def is_prime(n):
    if n < 2:
        return False
    for i in range(2, int(math.sqrt(n)) + 1):
        if n % i == 0:
            return False
    return True

def find_primes_parallel(numbers):
    with Pool(processes=cpu_count()) as pool:
        results = pool.map(is_prime, numbers)
    return results

numbers = range(1000000, 1010000)
primes = find_primes_parallel(numbers)
+------------------------+
|   主進(jìn)程 (協(xié)調(diào)者)       |
+------------------------+
          |
    +-----+-----+
    |           |
    v           v
+-------+   +-------+
| 進(jìn)程1 |   | 進(jìn)程2 |
|       |   |       |
|  ??GIL |   |  ??GIL |  ← 每個進(jìn)程有獨立的GIL
+-------+   +-------+

2. 使用 C 擴(kuò)展

// primes.c
#include <Python.h>

static PyObject* find_primes_c(PyObject* self, PyObject* args) {
    Py_BEGIN_ALLOW_THREADS  // 釋放 GIL
    // 執(zhí)行計算密集型任務(wù)
    Py_END_ALLOW_THREADS    // 重新獲取 GIL
    return Py_BuildValue("i", result);
}
+-----------------------+
|   Python 線程         |
+-----------------------+
          |
          v
+-----------------------+
|   釋放 GIL 的 C 擴(kuò)展   | ← 在C代碼中手動釋放GIL
+-----------------------+
          |
          v
+-----------------------+
|   并行計算 (無GIL限制)  |
+-----------------------+

3. 使用其他 Python 實現(xiàn)

  • Jython: 基于 JVM,沒有 GIL
  • IronPython: 基于 .NET,沒有 GIL
  • PyPy: 有 GIL,但性能更好
+----------------+----------------+----------------+
|   CPython      |   Jython       |   IronPython   |
|   (有GIL)       |   (無GIL)      |   (無GIL)      |
+----------------+----------------+----------------+

4. 使用異步編程

import asyncio
import aiohttp

async def download_site_async(session, url):
    async with session.get(url) as response:
        content = await response.read()
        print(f"Read {len(content)} from {url}")

async def download_all_sites_async(sites):
    async with aiohttp.ClientSession() as session:
        tasks = []
        for url in sites:
            task = asyncio.create_task(download_site_async(session, url))
            tasks.append(task)
        await asyncio.gather(*tasks)

# 運行異步任務(wù)
asyncio.run(download_all_sites_async(sites))

GIL 的優(yōu)缺點

優(yōu)點

  • 簡化 CPython 實現(xiàn)
  • 使單線程程序更快(無鎖開銷)
  • 更容易集成非線程安全的 C 擴(kuò)展

缺點

  • 限制多核 CPU 的利用率
  • 對 CPU 密集型多線程程序不友好
  • 可能造成性能誤解

實際開發(fā)建議

# 根據(jù)任務(wù)類型選擇方案:

def choose_concurrency_method(task_type, data):
    if task_type == "cpu_intensive":
        # 使用多進(jìn)程
        with multiprocessing.Pool() as pool:
            return pool.map(process_data, data)
    
    elif task_type == "io_intensive":
        # 使用多線程或異步
        with ThreadPoolExecutor() as executor:
            return list(executor.map(process_data, data))
    
    elif task_type == "mixed":
        # 混合方案:進(jìn)程池 + 線程池
        pass

未來展望

Python 社區(qū)正在探索移除 GIL 的方案:

  • nogil 分支:嘗試移除 GIL 的實驗性版本
  • subinterpreters:通過多個解釋器實例實現(xiàn)真正的并行

總結(jié)

GIL 是 CPython 的歷史遺留問題,它:

  • 主要影響 CPU 密集型多線程程序
  • 對 I/O 密集型任務(wù)影響較小
  • 可以通過多進(jìn)程、C 擴(kuò)展、異步編程等方式繞過

到此這篇關(guān)于Python GIL(全局解釋器鎖)的使用小結(jié)的文章就介紹到這了,更多相關(guān)Python GIL全局解釋器鎖內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Python  pandas中的shift位移操作方法

    Python  pandas中的shift位移操作方法

    shift()?函數(shù)是?Pandas?中用于移動或偏移數(shù)據(jù)的重要工具,它可以處理時間序列數(shù)據(jù)、計算數(shù)據(jù)差值以及進(jìn)行數(shù)據(jù)預(yù)處理,本文介紹Python  pandas中的shift位移操作方法,感興趣的朋友跟隨小編一起看看吧
    2024-03-03
  • 深入了解python中的常見錯誤類型與解決

    深入了解python中的常見錯誤類型與解決

    在Python編程過程中,經(jīng)常會遇到各種錯誤,了解這些錯誤的類型以及如何處理它們是成為一位優(yōu)秀的Python開發(fā)者所必備的技能之一,下面就跟隨小編一起學(xué)習(xí)一下python中的常見錯誤類型吧
    2023-11-11
  • python制作簡單五子棋游戲

    python制作簡單五子棋游戲

    這篇文章主要為大家詳細(xì)介紹了python制作簡單五子棋游戲,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-06-06
  • pytorch 計算ConvTranspose1d輸出特征大小方式

    pytorch 計算ConvTranspose1d輸出特征大小方式

    這篇文章主要介紹了pytorch 計算ConvTranspose1d輸出特征大小方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-06-06
  • Python使用tarfile模塊實現(xiàn)免費壓縮解壓

    Python使用tarfile模塊實現(xiàn)免費壓縮解壓

    Python自帶的tarfile模塊可以方便讀取tar歸檔文件,厲害的是可以處理使用gzip和bz2壓縮歸檔文件tar.gz和tar.bz2,這篇文章主要介紹了Python使用tarfile模塊實現(xiàn)免費壓縮解壓,需要的朋友可以參考下
    2024-03-03
  • python實現(xiàn)哈希表

    python實現(xiàn)哈希表

    介紹一個用python實現(xiàn)的哈希表,處理沖突的方法是開放地址法,沖突表達(dá)式為Hi=(H(key)+1)mod m,m為表長。遲點再實現(xiàn)更難的拉鏈法
    2014-02-02
  • pytorch中index_select()的用法詳解

    pytorch中index_select()的用法詳解

    這篇文章主要介紹了pytorch中index_select()的用法詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • Python 相對路徑報錯:"No such file or directory"'原因及解決方法

    Python 相對路徑報錯:"No such file or 

    如果你取相對路徑不是在主文件里,可能就會有相對路徑問題:"No such file or directory",由于python 的相對路徑,相對的都是主文件所以會出現(xiàn)Python 相對路徑報錯,今天小編給大家?guī)砹送昝澜鉀Q方案,感興趣的朋友一起看看吧
    2023-02-02
  • Python 中使用 Selenium 單擊網(wǎng)頁按鈕功能

    Python 中使用 Selenium 單擊網(wǎng)頁按鈕功能

    Selenium是一個用于測試網(wǎng)站的自動化測試工具,支持各種瀏覽器包括Chrome、Firefox、Safari等主流界面瀏覽器,同時也支持phantomJS無界面瀏覽器,本篇文章將介紹如何在 Python 中使用 selenium 單擊網(wǎng)頁上的按鈕,感興趣的朋友一起看看吧
    2023-11-11
  • Python列表切片常用操作實例解析

    Python列表切片常用操作實例解析

    這篇文章主要介紹了Python列表切片常用操作實例解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-12-12

最新評論

东港市| 乐陵市| 东乌珠穆沁旗| 万安县| 麟游县| 崇义县| 德庆县| 柳州市| 大冶市| 淅川县| 卫辉市| 铜陵市| 阳谷县| 凤台县| 三江| 福泉市| 普定县| 中牟县| 五常市| 晴隆县| 重庆市| 苏州市| 大理市| 桦甸市| 尼勒克县| 体育| 夏津县| 隆德县| 黎川县| 墨玉县| 呼伦贝尔市| 曲松县| 保德县| 宁化县| 沅江市| 石渠县| 包头市| 合肥市| 会理县| 剑川县| 丘北县|