多線程與多進程的思考

64 人贊了文章

在一個系統需要並發的時候,就會思考多線程還是多進程的實現(這裡先不考慮GPU、FPGA這些並行加速的東西)

看了一些知友的討論【1】、【2】、【3】,還是收穫了不少,結合別的資料,在這裡對多進程和多線程進行一個梳理,有什麼說的不太好的還請見諒。

  • 進程和線程的理解

在【4】中,進程和線程的關係就用圖描述得非常清楚。一個進程裡面可以有多個線程,這個進程有自己的資源【5】:某個程序的鏡像,比如我們使用多進程fork出的新進場,都會有執行fork函數的指令,我們可以稱之為鏡像。分配了一定大小的虛擬內存,包含了需要執行的之類,輸入和輸出。調用棧,用於fork返回,處理某些特殊的event。堆用於存儲中間數據,就是fork函數出來以後,執行這個函數產生的中間數據。在一個進程中,可以有多個線程,多個線程可以共享進程裡面的數據【4】,【6】,比如堆、全局變數、靜態變數等等。有的資源需要獨佔,就可以加互斥鎖(mutex),只允許此處的資源獨佔。有的資源有一定的容量,就會加信號量(semaphore)。所以我們可以看出進程與線程之間屬於從屬關係。線程的資源一定程度上受限於進程,但是線程的通信會比進程間通信更加快捷。

一般來說,一個進程在運行使用CPU時是獨佔一個核的,但是由於分時系統存在,所以可以有多進程並發。在多核中,每個核都可以跑一個進程,那麼就可以實現並行【3】。

  • 多線程與多進程的通信

在【10】,【11】中介紹了多線程和多進程的之間的數據通信方法。進程間通信(IPC)會使用管道(pipe,父子進程間),流管道(s_pipe,可雙向的父子進程)和有名管道(FIFO),信號(signal,控制資源使用), 消息隊列(message queue),共享內存(由一個進程創建,別的進程都可以訪問的地址),信號量,套接字(socket,ROS就是採用該方法進行進程間通信) 進行通信。共享內存是最快的方式,共享內存的通信方式是通過將共享的內存緩衝區直接附加到進程的虛擬地址空間中來實現的,因此,這些進程之間的讀寫操作的同步問題操作系統無法實現。必須由各進程利用其他同步工具解決。另外,由於內存實體存在於計算機系統中,所以只能由處於同一個計算機系統中的諸進程共享。不方便網路通信。 共享內存塊提供了在任意數量的進程之間進行高效雙向通信的機制。每個使用者都可以讀取寫入數據,但是所有程序之間必須達成並遵守一定的協議,以防止諸如在讀取信息之前覆寫內存空間等競爭狀態的出現。 不幸的是,Linux無法嚴格保證提供對共享內存塊的獨佔訪問,甚至是在您通過使用IPC_PRIVATE創建新的共享內存塊的時候也不能保證訪問的獨佔性。 同時,多個使用共享內存塊的進程之間必須協調使用同一個鍵值。

線程一般採用鎖,信號,信號量進行同一個進程內線程間通信。但是線程間有共享數據,所以也是可以直接進行內存的寫,但是不同線程的數據同步就需要做一些優化。比如在OpenMP中就會有local variable去除false sharing。

  • 多線程與多進程的特點

進程更加安全,進程間獨立,一個進程掛了不會影響到別的進程。進程創建時間比較長,遠遠長於線程。進程相對於線程最大的區別是有內核保證的隔離:數據和錯誤隔離。對於使用如C/C++這些語言編寫的本地代碼,錯誤隔離是非常有用的:採用多進程架構的程序一般可以做到一定程度的自恢復。進程上下文切換時間高於線程上下文切換。線程有較輕的上下文切換開銷,不用切換地址空間,不用更改CR3寄存器,不用清空TLB。進程間通信效率不如線程通信,線程可以進行方便高效的內存共享,多進程下內存共享比較不便,且會抵消掉多進程編程的好處。

線程在新建和回收的效率上很高,但它還是一個耗時的操作,所以需要線程池等來加快這一類操作。線程之間的通信可以直接訪問內存。

用【8】中的一幅圖概括就是:

  • 多線程與多進程的選擇

多進程可以使得系統魯棒性更高,出錯的時候容易找到錯誤的地方,而且不影響別的進程。所以在絕大多數的自動駕駛操作系統中,會使用多進程的發案,比如ROS,比如Apollo。如果是分散式,就用多進程。

多線程可以進行快速創建和數據共享,進程創建的開銷很大,上下文切換開銷也稍微大一些,頻繁創建進程去響應伺服器的請求會造成極大的開銷,而且會增加響應時間,所以在進行伺服器響應的時候會採用多線程。如果是多核處理用多線程。

其實說了這麼多,在Linux裡面,進程和線程的實現是一樣的,只是兩者可以使用的資源不一樣。沒想到吧~ 所以選擇多線程和多進程也沒有絕對的,要看業務場景以及所擁有的資源。

參考:

【1】為什麼需要多線程? Linux中進程和線程的開銷基本一樣啊,為什麼還要多線程呢?

【2】多線程與多進程更適合什麼任務: Linux 下多線程和多進程程序的優缺點,各自適合什麼樣的業務場景?

【3】多個進程可以並行執行在多核CPU上么: 多核CPU 是否能同時執行多個進程?

【4】進程與線程的一個簡單解釋 - 阮一峰的網路日誌

【5】Process (computing)

【6】多線程之間共享哪些資源? - CSDN博客

【7】program-think.blogspot.com

【8】多線程還是多進程的選擇及區別 - 賀大衛 - 博客園

【9】Operating System | Difference between multitasking, multithreading and multiprocessing - GeeksforGeeks

【10】Linux進程間通信的幾種方式總結--linux內核剖析(七) - CSDN博客

【11】Linux的進程/線程間通信方式總結 - CSDN博客

【12】geeksforgeeks.org/opera


推薦閱讀:
查看原文 >>
相关文章