multithreading - data - python threading教學




進程和線程有什麼區別? (20)

應用程序由一個或多個進程組成。 一個最簡單的過程就是一個執行程序。 一個或多個線程在進程的上下文中運行。 線程是操作系統分配處理器時間的基本單位。 線程可以執行進程代碼的任何部分,包括當前由另一個線程執行的部分。 光纖是必須由應用程序手動調度的執行單元。 光纖在安排它們的線程的上下文中運行。

herehere

進程和線程之間的技術區別是什麼?

我感覺像'過程'這樣的詞被過度使用,並且還有硬件和軟件線程。 Erlang語言中的輕量級過程如何? 有一個明確的理由使用一個術語而不是另一個術語?


  1. 基本上,線程是進程的一部分,沒有進程線程無法工作。
  2. 線程是輕量級的,而過程是重量級的。
  3. 進程之間的通信需要一些時間,而線程需要更少的時間
  4. 線程可以共享相同的內存區域,而進程獨立存在。

線程與進程的區別?

進程是應用程序的執行實例,線程是進程內的執行路徑。 另外,一個進程可以包含多個線程。重要的是要注意一個線程可以完成一個進程可以執行的任何操作。 但是由於一個進程可以由多個線程組成,因此一個線程可以被認為是一個“輕量級”進程。 因此,線程和進程之間的本質區別就是每個人用來完成的工作。 線程用於小任務,而進程用於更多“重量級”任務 - 基本上是應用程序的執行。

線程和進程之間的另一個區別是同一進程內的線程共享相同的地址空間,而不同的進程則不同。 這允許線程讀取和寫入相同的數據結構和變量,並且還促進線程之間的通信。 過程之間的通信 - 也被稱為IPC或進程間通信 - 是相當困難和資源密集型的。

以下是線程和進程之間的區別摘要:

  1. 線程比流程更容易創建,因為它們不需要單獨的地址空間。

  2. 多線程需要仔細編程,因為線程共享一次只能由一個線程修改的數據結構。 與線程不同,進程不共享相同的地址空間。

  3. 線程被認為是輕量級的,因為它們比進程使用的資源要少得多。

  4. 進程是彼此獨立的。 線程,因為它們共享相同的地址空間是相互依賴的,所以必須小心謹慎,以便不同的線程不會互相影響。
    這是說明上述#2的另一種方式。

  5. 一個進程可以由多個線程組成。


流程和線程的真實世界示例 這將給您關於線程和流程的基本概念

我從Scott Langham的答案中藉用了上述信息 - 謝謝


處理:

  • 程序的執行實例稱為進程。
  • 一些操作系統使用術語“任務”來指代正在執行的程序。
  • 進程總是存儲在主存儲器中,也稱為主存儲器或隨機存取存儲器。
  • 因此,一個過程被稱為活動實體。 如果機器重新啟動,它會消失。
  • 幾個過程可能與同一個程序相關聯。
  • 在多處理器系統上,可以並行執行多個進程。
  • 在單處理器系統上,儘管沒有實現真正的並行性,但是應用了進程調度算法,並且處理器被調度為每次執行一個進程,產生並發幻覺。
  • 示例:執行“計算器”程序的多個實例。 每個實例都被稱為一個進程。

線:

  • 線程是進程的一個子集。
  • 它被稱為“輕量級進程”,因為它類似於真實進程,但在進程的上下文中執行,並共享內核分配給進程的相同資源。
  • 通常,一個進程只有一個控制線程 - 一次執行一組機器指令。
  • 一個進程也可以由多個執行線程並發執行指令組成。
  • 多個控制線程可以利用多處理器系統上的真正並行性。
  • 在單處理器系統上,應用線程調度算法,並且處理器計劃每次運行一個線程。
  • 一個進程中運行的所有線程共享相同的地址空間,文件描述符,堆棧和其他進程相關的屬性。
  • 由於進程的線程共享相同的內存,所以將對共享數據的訪問與進程同步獲得前所未有的重要性。

我借鑒了知識任務中的以上信息 博客


處理:

  1. 過程是一個沉重的過程。
  2. 進程是一個單獨的程序,具有獨立的內存,數據,資源等。
  3. 過程使用fork()方法創建。
  4. 進程之間的上下文切換非常耗時。

例:
說,打開任何瀏覽器(Mozilla,Chrome,IE)。 此時新流程將開始執行。

主題:

  1. 線程是輕量級進程。線程捆綁在進程內。
  2. 線程有一個共享內存,數據,資源,文件等
  3. 線程是使用clone()方法創建的。
  4. 線程之間的上下文切換不像Process那麼耗時。

例:
在瀏覽器中打開多個選項卡。


以下是我從“守則項目”的其中一篇文章中得到的內容。 我想這可以解釋清楚所需的一切。

線程是將工作負載分解為單獨的執行流的另一種機制。 線程比過程輕。 這意味著,它提供的靈活性比完整流程少,但可以更快地啟動,因為操作系統設置的次數更少。 當一個程序由兩個或多個線程組成時,所有線程共享一個內存空間。 進程被賦予單獨的地址空間。 所有線程共享一個堆。 但是每個線程都有自己的堆棧。


來自嵌入式世界,我想補充一點,進程的概念只存在於具有MMU(內存管理單元)的“大型”處理器( 台式機CPU,ARM Cortex A-9 )以及支持使用MMU的操作系統如Linux )。 對於小型/舊型處理器和微控制器以及小型RTOS操作系統( 實時操作系統 )(如freeRTOS),不存在MMU支持,因此沒有進程,只有線程。

線程可以訪問每個其他內存,並且它們按照交錯的方式由操作系統進行調度,以便它們似乎可以並行運行(或者使用多核並行運行)。

另一方面, 進程存在於由MMU提供和保護的虛擬內存私有沙箱中。 這很方便,因為它可以:

  1. 讓整個系統崩潰的錯誤過程。
  2. 通過使其他進程數據不可見和不可訪問來維護安全。 流程中的實際工作由一個或多個線程處理。

嘗試從Linux Kernel的OS View中回答它

一個程序在啟動到內存後就成為一個進程。 一個進程有自己的地址空間,這意味著內存中有不同的段,例如用於存儲編譯代碼的.text segement,用於存儲未初始化的靜態或全局變量的.bss等等。每個進程都有自己的程序計數器和用戶級存儲 。 在內核中,每個進程都有自己的內核堆棧(為了安全問題與用戶空間堆棧分開)和一個名為task_struct的結構,它通常被抽象為進程控制塊,存儲所有關於進程的信息,例如其優先級,狀態,(和其他很多塊)。 一個進程可以有多個執行線程。

來到線程,它們駐留在一個進程中,並共享父進程的地址空間以及線程創建期間可以傳遞的其他資源,例如文件系統資源,共享未決信號,共享數據(變量和指令),從而使線程輕量級,因此允許更快的上下文切換 在內核中,每個線程都有自己的內核堆棧以及定義線程的task_struct結構。 因此內核查看與不同實體相同進程的線程,並且可以自行調度。 同一進程中的線程共享一個稱為線程組ID( tgid )的公共ID,並且它們具有稱為進程ID( pid )的唯一ID。


在構建包含多線程的Python(解釋型語言)中的算法時,我驚訝地發現,與我之前構建的順序算法相比,執行時間並沒有更好。 為了理解這個結果的原因,我做了一些閱讀,並且相信我學到的東西提供了一個有趣的背景,從中可以更好地理解多線程和多進程之間的差異。

多核系統可以執行多個線程,所以Python應該支持多線程。 但是Python不是一種編譯語言,而是一種解釋型語言1 。 這意味著程序必須被解釋才能運行,並且解釋程序在開始執行之前並不知道該程序。 但是,它所知道的是Python的規則,然後它動態地應用這些規則。 Python中的優化必須主要優化解釋器本身,而不是要運行的代碼。 這與諸如C ++之類的編譯語言形成對比,並且對Python中的多線程產生影響。 具體來說,Python使用Global Interpreter Lock來管理多線程。

另一方面,編譯好的語言已經編譯好了。 程序完全處理,首先根據其語法定義進行解釋,然後映射到語言不可知的中間表示,最後鏈接成可執行代碼。 這個過程允許代碼高度優化,因為它在編譯時都是可用的。 各種程序交互和關係是在創建可執行文件時定義的,並且可以做出關於優化的穩健決策。

在現代環境中,Python的解釋器必須允許多線程,並且這必須既安全又高效。 這就是解釋型語言與編譯型語言之間的差異進入圖片的地方。 解釋器不得乾擾來自不同線程的內部共享數據,同時優化處理器的計算使用。

如前所述,進程和線程都是獨立的順序執行,主要區別在於內存在進程的多個線程之間共享,而進程則隔離它們的內存空間。

在Python中,全局解釋器鎖可防止不同線程同時訪問數據。 它要求在任何Python程序中只有一個線程可以隨時執行。 另一方面,可以運行多個進程,因為每個進程的內存都與其他進程隔離,並且進程可以在多個內核上運行。

1 Donald Knuth對“計算機程序設計藝術:基礎算法”中的解釋程序有很好的解釋。


從採訪者的角度來看,我基本上只想听到3件主要的事情,除了像流程這樣明顯的東西可以有多個線程:

  1. 線程共享相同的內存空間,這意味著線程可以從其他線程內存訪問內存。 過程通常不能。
  2. 資源。 資源(內存,句柄,套接字等)在進程終止時釋放,而不是線程終止。
  3. 安全。 一個進程有一個固定的安全令牌。 另一方面,線程可以模擬不同的用戶/令牌。

如果你想要更多,Scott Langham的回應幾乎涵蓋了一切。 所有這些都來自操作系統的角度。 不同的語言可以實現不同的概念,如任務,輕便線程等,但它們只是使用線程(Windows上的光纖)的方式。 沒有硬件和軟件線程。 有硬件和軟件異常中斷 ,或用戶模式和內核線程


更多關於並發編程的解釋

  1. 一個進程有一個獨立的執行環境。 一個進程通常有一套完整的私有基本運行時資源; 特別是每個進程都有自己的內存空間。

  2. 線程存在於一個進程中 - 每個進程至少有一個線程。 線程共享進程的資源,包括內存和打開的文件。 這使得溝通有效但可能有問題。

記住一般人,

在您的計算機上,打開Microsoft Word和Web瀏覽器。 我們稱之為這兩個過程

在微軟的話,你輸入一些東西,它會自動保存。 現在,你會觀察到並行編輯和保存 - 在一個線程上編輯並保存在另一個線程上。


線程和進程都是操作系統資源分配的原子單位(即有一個描述CPU時間如何分配的並發模型,以及擁有其他操作系統資源的模型)。 有以下不同之處:

  • 共享資源(線程根據定義共享內存,除了堆棧和局部變量外,它們不擁有任何內容;進程也可以共享內存,但是由OS維護的還有一個單獨的機制)
  • 分配空間(進程的內核空間與線程的用戶空間)

上面的Greg Hewgill對於“process”一詞的Erlang含義是正確的, here有一個關於Erlang為什麼可以做輕量級處理的討論。


線程是CPU利用率的基本單位; 它包含線程ID,程序計數器,寄存器組和堆棧。 它與屬於同一進程的其他線程的代碼段,數據段和其他操作系統資源(如打開的文件和信號)共享。 傳統(或重量級)流程具有單一控制線程。 如果一個進程有多個控制線程,它一次可以執行多個任務


試圖回答這個與Java世界有關的問題。

進程是程序的執行,但線程是進程內的單個執行序列。 一個進程可以包含多個線程。 線程有時稱為輕量級進程

例如:

示例1:JVM在單個進程中運行,JVM中的線程共享屬於該進程的堆。 這就是為什麼幾個線程可以訪問同一個對象。 線程共享堆並擁有自己的堆棧空間。 這是一個線程如何調用一個方法以及它的局部變量是如何保持線程安全的。 但是堆不是線程安全的並且為了線程安全必須進行同步。

示例2:程序可能無法通過讀取按鍵來繪製圖片。 該程序必須充分注意鍵盤輸入,並且缺乏一次處理多個事件的能力將導致麻煩。 解決此問題的理想解決方案是同時無縫執行程序的兩個或更多部分。 線程允許我們這樣做。 這裡畫圖是一個過程,讀擊鍵是子過程(線程)。


迄今為止我所見過的最好的短期定義來自Michael Kerrisk的“The Linux Programming Interface”:

在現代UNIX實現中,每個進程可以有多個執行線程。 設想線程的一種方式是共享相同虛擬內存的一組進程,以及一系列其他屬性。 每個線程正在執行相同的程序代碼並共享相同的數據區和堆。 但是,每個線程都有自己的包含本地變量和函數調用鏈接信息的堆棧。 [LPI 2.12]


進程和線程都是獨立的執行序列。 典型的區別是線程(同一進程的)在共享內存空間中運行,而進程在單獨的內存空間中運行。

處理

是一個正在執行的程序。 它具有文本部分,即程序代碼,當前活動由程序計數器的值和處理器內容寄存器表示。 它還包含包含臨時數據(例如函數參數,返回地址和局部變量)的過程堆棧以及包含全局變量的數據部分。 一個進程也可能包含一個堆,它是在進程運行時動態分配的內存。

線程是CPU利用率的基本單位; 它包含線程ID,程序計數器,寄存器集和堆棧。 它與屬於同一進程的其他線程共享其代碼段,數據段和其他操作系統資源,如打開的文件和信號。

- 來自Galvin的操作系統


進程是代碼,內存,數據和其他資源的集合。 線程是在進程範圍內執行的一系列代碼。 您可以(通常)在同一進程中同時執行多個線程。


進程是應用程序的執行實例。 那是什麼意思? 那麼,例如,當您雙擊Microsoft Word圖標時,就會啟動運行Word的進程。 線程是進程內的執行路徑。 另外,一個進程可以包含多個線程。 當您啟動Word時,操作系統將創建一個進程並開始執行該進程的主線程。

重要的是要注意一個線程可以完成一個進程可以做的任何事情。 但是由於一個進程可以由多個線程組成,因此一個線程可以被認為是一個“輕量級”進程。 因此,線程和進程之間的本質區別就是每個人用來完成的工作。 線程用於小任務,而進程用於更多“重量級”任務 - 基本上是應用程序的執行。

線程和進程之間的另一個區別是同一進程內的線程共享相同的地址空間,而不同的進程則不同。 這允許線程讀取和寫入相同的數據結構和變量,並且還促進線程之間的通信。 過程之間的通信 - 也被稱為IPC或進程間通信 - 是相當困難和資源密集型的。


首先,我們來看看理論方面。 您需要理解流程在概念上是什麼,才能理解流程和線程之間的差異以及它們之間共享的內容。

我們從2.2.2節Tanenbaum的現代操作系統3e中 的經典線程模型

流程模型基於兩個獨立的概念:資源分組和執行。 有時將它們分開是有用的; 這是線程進入的地方....

他繼續:

查看流程的一種方式是,它可以將相關資源分組在一起。 進程具有包含程序文本和數據的地址空間以及其他資源。 這些資源可能包括打開的文件,子進程,待處理的警報,信號處理程序,會計信息等等。 通過將它們以流程的形式放在一起,可以更輕鬆地進行管理。 過程所具有的另一個概念是執行的線程,通常簡稱為線程。 線程有一個程序計數器,用於跟踪下一個要執行的指令。 它有寄存器,它保存當前的工作變量。 它有一個包含執行歷史的堆棧,每個過程調用一個幀但尚未返回。 雖然線程必須在某個進程中執行,但線程及其進程是不同的概念,可以分別處理。 過程用於將資源組合在一起; 線程是計劃在CPU上執行的實體。

再往下,他提供了下表:

Per process items             | Per thread items
------------------------------|-----------------
Address space                 | Program counter
Global variables              | Registers
Open files                    | Stack
Child processes               | State
Pending alarms                |
Signals and signal handlers   |
Accounting information        |

我們來處理硬件多線程問題。 通常,CPU將支持單個執行線程,通過單個程序計數器和一組寄存器來維護線程的狀態。 但是如果有一個緩存未命中會發生什麼? 從主存儲器獲取數據需要很長時間,而這種情況發生時,CPU只是坐在那裡閒置。 所以有人想到基本上有兩組線程狀態(PC +寄存器),以便另一個線程(可能在同一進程中,也許在另一個進程中)可以在另一個線程在主存儲器上等待時完成工作。 這個概念有多種名稱和實現,例如超線程和同時多線程 (簡稱SMT)。

現在讓我們看看軟件方面。 基本上有三種方法可以在軟件方面實現線程。

  1. 用戶空間線程
  2. 內核線程
  3. 兩者的結合

您需要實現線程的所有功能都是能夠保存CPU狀態並維護多個堆棧,在很多情況下可以在用戶空間中完成。 用戶空間線程的優點是超快速的線程切換,因為您不必陷入內核並能夠按照自己喜歡的方式安排線程。 最大的缺點是無法阻止I / O(阻塞整個進程以及它的所有用戶線程),這是我們首先使用線程的一個重要原因。 在很多情況下,使用線程阻塞I / O大大簡化了程序設計。

內核線程的優點是能夠使用阻塞I / O,除了將所有調度問題留給操作系統。 但是每個線程切換都需要陷入可能相對較慢的內核中。 但是,如果因為I / O阻塞而切換線程,這並不是一個真正的問題,因為I / O操作可能已經將您困在內核中了。

另一種方法是將兩者結合起來,使用多個內核線程,每個線程都有多個用戶線程。

回過頭來看術語問題,你可以看到一個過程和一個執行線程是兩個不同的概念,你選擇使用哪個術語取決於你在說什麼。 關於“輕量級過程”這個術語,我個人並沒有看到它的意義,因為它並沒有真正傳達正在發生的事情以及“執行線程”這個術語。







process