Python 併發性 - 簡介



本章將介紹 Python 中併發的概念,並學習不同的執行緒和程序。

什麼是併發?

簡單來說,併發是兩個或多個事件同時發生。併發是一種自然現象,因為在任何給定時間,許多事件會同時發生。

在程式設計方面,併發是指兩個任務在執行上重疊。透過併發程式設計,可以提高應用程式和軟體系統的效能,因為我們可以併發處理請求,而不是等待前一個請求完成。

併發的歷史回顧

以下幾點將簡要回顧併發的歷史:

從鐵路概念出發

併發與鐵路概念密切相關。在鐵路系統中,需要以確保每列火車都能安全到達目的地的方式來處理同一鐵路系統上的多列火車。

學術界的併發計算

計算機科學對併發的興趣始於 Edsger W. Dijkstra 在 1965 年發表的研究論文。在這篇論文中,他識別並解決了互斥問題,這是併發控制的一個屬性。

高階併發原語

近年來,由於引入了高階併發原語,程式設計師正在獲得改進的併發解決方案。

程式語言改進的併發性

諸如 Google 的 Golang、Rust 和 Python 等程式語言在幫助我們獲得更好的併發解決方案的領域取得了令人難以置信的進展。

什麼是執行緒和多執行緒?

執行緒是作業系統中可以執行的最小執行單元。它本身不是一個程式,而是在程式中執行。換句話說,執行緒彼此不獨立。每個執行緒與其他執行緒共享程式碼段、資料段等。它們也稱為輕量級程序。

執行緒包含以下元件:

  • 程式計數器,包含下一個可執行指令的地址

  • 堆疊

  • 暫存器集

  • 一個唯一 ID

另一方面,多執行緒是指 CPU 透過併發執行多個執行緒來管理作業系統使用的能力。多執行緒的主要思想是透過將一個程序分成多個執行緒來實現並行性。可以透過以下示例理解多執行緒的概念。

示例

假設我們正在執行一個特定的程序,在這個程序中,我們開啟 MS Word 向其中鍵入內容。一個執行緒將被分配來開啟 MS Word,另一個執行緒將被需要在其中鍵入內容。現在,如果我們想編輯現有的內容,則需要另一個執行緒來執行編輯任務,依此類推。

什麼是程序和多程序?

程序被定義為一個實體,它表示要在系統中實現的基本工作單元。簡單來說,我們用文字檔案編寫計算機程式,當我們執行這個程式時,它就變成了一個執行程式中所有任務的程序。在程序生命週期中,它會經歷不同的階段——啟動、就緒、執行、等待和終止。

下圖顯示了程序的不同階段:

Multiprocessing

一個程序可以只有一個執行緒(稱為主執行緒),也可以有多個執行緒,每個執行緒都有自己的一組暫存器、程式計數器和堆疊。下圖將顯示它們的區別:

Multiprocessing One

另一方面,多程序是在單個計算機系統中使用兩個或多個 CPU 單元。我們的主要目標是充分發揮硬體的潛能。為此,我們需要利用計算機系統中可用的所有 CPU 核心。多程序是實現此目標的最佳方法。

Multiprocessing Two

Python 是最流行的程式語言之一。以下是一些使其適合併發應用程式的原因:

語法糖

語法糖是在程式語言中設計的語法,旨在使程式碼更易於閱讀或表達。它使語言對人類來說更“甜蜜”:可以更清晰、更簡潔地表達事物,或者根據偏好採用替代風格。Python 帶有魔術方法,可以定義為對物件進行操作。這些魔術方法用作語法糖,並繫結到更易於理解的關鍵字。

大型社群

Python 語言在從事 AI、機器學習、深度學習和定量分析領域工作的數​​據科學家和數學家中獲得了巨大的採用率。

用於併發程式設計的有用 API

Python 2 和 3 有大量專用於並行/併發程式設計的 API。最流行的是threading、concurrent.features、multiprocessing、asyncio、gevent 和 greenlets 等。

Python 在實現併發應用程式方面的侷限性

Python 在併發應用程式方面存在一個限制。這個限制被稱為GIL(全域性直譯器鎖)存在於 Python 中。GIL 從不允許我們利用 CPU 的多個核心,因此我們可以說 Python 中沒有真正的執行緒。我們可以理解 GIL 的概念如下:

GIL(全域性直譯器鎖)

這是 Python 世界中最具爭議的話題之一。在 CPython 中,GIL 是互斥鎖——互斥鎖,它使事情執行緒安全。換句話說,我們可以說 GIL 阻止多個執行緒並行執行 Python 程式碼。一次只能由一個執行緒持有該鎖,如果我們想執行一個執行緒,則它必須首先獲取該鎖。下圖將幫助您瞭解 GIL 的工作原理。

Limitations

但是,Python 中有一些庫和實現,例如Numpy、JpythonIronPytbhon。這些庫無需與 GIL 進行任何互動即可工作。

廣告