多道程序設計和多線程有什麼區別?

帶你一起周遊世界 發佈 2023-02-16T01:17:11.077316+00:00

多任務處理(英語:Computer multitasking)是指計算機同時運行多個程序的能力。

多任務處理(英語:Computer multitasking)是指計算機同時運行多個程序的能力。多任務的一般方法是運行第一個程序的一段代碼,保存工作環境;再運行第二個程序的一段代碼,保存環境;……恢復第一個程序的工作環境,執行第一個程序的下一段代碼……現代的多任務,每個程序的時間分配相對平均。計算機的早期,多任務被稱作多道程序(multiprogramming)。多道程序是令CPU一次讀取多個程序放入內存,先運行第一個程序直到它出現了IO操作。因為IO操作慢,CPU需要等待。為了提高CPU利用率,此時運行第二個程序。即,第n+1個程序得以執行的條件是第n個程序進行IO操作或已經運行完畢。這種方式每個程序的時間分配是不均等的,很可能第一個程序運行了幾個小時而不出現IO操作,故第二個程序沒有運行。在當初,這種情況是令人接受的。人們一次指定運行多個程序,過幾個小時或一天後來看運行結果或拿走列印出來的文件。人們不需要實時獲得每個程序的運行情況,只關心運行結果。

多線程編程中常見的錯誤有哪些?

在線程之間創建不必要的依賴關係(也讀取共享資源)——在線程之間不必要地共享數據並使用鎖訪問數據不利於多線程程序的性能。因此,儘可能使用 MPICH 方法進行多線程編程是有益的。這個想法是將您的輸入數據分成不重疊的集合,並將每個集合分配給一個線程。最後,您的主線程將負責從工作線程收集子結果,並將它們組合起來。這種方法也用於 STL 算法的並行版本的實現。

過度鎖定——鎖定儘可能少的共享數據和指令,並在對shared_data操作完成後立即解鎖。

獲取鎖後休眠——在多線程程序中,共享數據是所有線程都在爭奪的寶貴資源。線程設法使用鎖獲得對資源的獨占訪問權。如果您的代碼獲得了鎖並進入休眠狀態,它會在代碼審查期間立即發出紅旗。

獲取鎖後的 I/O 操作 - 與 CPU 操作相比,I/O 操作非常慢。網絡操作也是如此。因此,一旦獲得鎖定,就應該避免執行 I/O 或網絡操作。

創建太多線程 - C++ 中的 std::thread::hardware_concurrency() 可以讓您很好地了解要在 C++ 程序中創建的最大線程數。如果你創建的線程比這更多,系統將在上下文切換中變得比執行你的程序更忙。

不使用 std::async - async 有助於將您的程序更像是一組任務,這比一堆線程更容易推理。異步是非阻塞的,也讓你免於創建過多線程的煩惱。

不使用原子 - 原子是無鎖的(僅適用於少數原始數據類型,基本用戶定義的數據結構),因此比使用鎖更快。

頻繁請求空閒內存存儲 - 您的程序只有一個內存管理器可用。當多個線程頻繁調用「new」時,這與使用鎖訪問共享數據一樣好。

linux Kernel 本身是多線程的嗎?

Linux 內核是一些聰明的程式設計師用了幾年時間編寫的一段高度優化的代碼。Linux、*BSD、macOS、Windows NT 等任何流行內核的情況也是如此。您可以認為 Linux 沒有針對給定功能的最佳算法,您可能是對的。然而,當任何 OS 開發人員發現更快更好的方法時,在許多情況下,可以獲得足夠的信息以允許具有競爭力的 OS Maintainer(包括 Linux)重新實現類似的功能。最後,您可以改進任何作業系統。但是,您不太可能找到像使用多線程這樣的新方法這樣容易實現的成果。如果是這樣的話,有人已經在作業系統文獻中記錄了它。

Linux 多線程 — 是/否(語義問題):與標準程序不同並在其初始化之後,大多數作業系統大多是事件驅動的。中斷機制是觸發大多數服務任務(如調度程序)執行的機制。然後,在適當的時候,調度程序將調用內核線程。

中斷是所有活動的基礎:所有外圍活動都是如此。當用戶空間程序使用軟體中斷(例如:Open (filex))調用內核例程時也是如此。linux可以同時;打開文件、路由 TCP/IP 數據包、服務 Wi-Fi 適配器、乙太網卡等等。但是,這些都不能被視為內核中的線程。因此,Linux 內核是多線程和事件驅動的。它可以執行多個任務/服務,所有任務/服務同時進行,並在適當的時候在多個處理器上執行。

內核中的重要優化:即使是最基本的內核也可以同時處理多個事件。單任務 MS-DOS 能夠檢測到 NMI 條件並開始執行第二個偽線程。<例如:CTRL-ALT-DELETE 序列>

重新進入:您可以安全地多次調用任何內核模塊,同時在多個處理器上。該概念甚至適用於單處理器系統,其中可重入過程可以在其執行過程中被中斷,然後在其先前的調用完成之前安全地重新進入。

中斷搶占:Linux 確實允許某些中斷搶占。它可以暫停低優先級中斷的執行,以更好地響應高優先級中斷。

細粒度內存鎖:內核必須確定兩個執行單元不會修改內存中的相同數據。Linux 有一個細粒度的內存鎖結構。這確實意味著 TCP/IP 表更新可以發生在另一個內核執行單元修改調度表或文件 inode 表等時。也有可能當 Wi-Fi 驅動程序訪問它處理的設備的內存表時,它可以在大部分時間完成它,而不會受到調度程序或其他執行單元的過多干擾。

實時項目場景中的多線程示例有哪些?

數學。想一想需要大量計算的數學問題,例如,求解一個龐大的線性方程組。如果您構建這樣一個模型,您可以將計算拆分為多個不相交的塊並獨立執行每個塊,那麼這可以更快地完成。完成後,您只需組合每個線程的結果。另一個例子是矩陣乘法。請注意,為了使這些操作真正高效,您的每個線程都應該在自己的處理器上運行(這有時稱為真正的並行性)

任務派發。當您有一個相關任務隊列時,線程很有用,每個任務都可以獨立執行。管理它們的實體稱為線程池。線程池為要運行的任務提供了一些線程。把它想像成一個工廠,有多個管道和一排盒子,上面有關於如何構建其中內容的說明。一個工作人員從隊列中取出一個盒子並將其放在管道上(如果有空閒的話)。Chromium 瀏覽器是這樣構建的:它有幾個線程,它們負責自己的事情。此外,一些線程有一個 MessageLoop 和 Tasks 隊列,它們也是自己執行的。

圖形用戶界面應用程式。分離呈現和執行過程。當你構建一個 GUI 應用程式時,你永遠不希望 GUI 凍結,因為用戶會立即驚慌失措。為什麼會結冰?當用戶與您的應用程式交互時,它始終會處理一些數據:更新、讀取和刪除某些內容。這需要時間和處理能力。因此,為了避免這種情況,一個事件調度隊列與您的 GUI 一起實現,以在單獨的線程中處理所有數據處理,同時您的 GUI 保持完整的功能並可以輕鬆響應您的操作。同樣,線程池在這裡可能很有用。

聯網。所有網絡例程(例如下載圖像)都可能需要時間並阻止您的應用程式執行。為避免這種情況,網絡通常在另一個線程中執行,儘管您最常看到的是針對此問題的術語異步執行。儘管理論上它是一種完全不同的執行方法,但它與我們之前討論的方法非常接近。

你的作業系統。您很可能正在運行一個現代作業系統,它們都採用多線程來保持自身的活力。作業系統必須同時控制很多事情,如果沒有多線程,就不可能如此高效地完成所有事情。同樣,前面討論的所有概念都適用於此。

多道程序設計和多線程有什麼區別?

多道程序

在多道程序系統中,主存中加載了一個或多個準備執行的程序。一次只有一個程序能夠獲得 CPU 來執行其指令(即,系統上最多運行一個進程),而所有其他程序都在等待輪到它們。多道程序設計的主要思想是最大限度地利用 CPU 時間。實際上,假設當前運行的進程正在執行 I/O 任務(根據定義,該任務不需要 CPU 來完成)。然後,作業系統可能會中斷該進程並將控制權交給準備執行的其他主內存程序之一(即進程上下文切換). 這樣,系統就不會浪費 CPU 時間來等待 I/O 任務完成,一個正在運行的進程會一直執行,直到它主動釋放 CPU 或阻塞 I/O 操作。因此,多道程序設計的最終目標是只要有進程準備執行就可以讓 CPU 保持忙碌。

請注意,為了使此類系統正常運行,作業系統必須能夠將多個程序加載到主內存的不同區域並提供所需的保護以避免一個進程被另一個進程修改的機會。當內存中有多個程序時需要解決的其他問題是碎片當程序進入或離開主存儲器時。另一個需要處理的問題是大型程序可能無法立即放入內存,這可以通過使用分頁和虛擬內存來解決。

最後,請注意,如果有N就緒進程並且所有這些進程都高度受 CPU 限制(即,它們主要執行 CPU 任務而沒有或很少執行 I/O 操作),在最壞的情況下,一個程序可能會等待所有其他N-1程序在執行之前完成。

多處理

多處理有時是指同時執行多個進程(程序)。這可能會產生誤導,因為我們之前已經引入了術語「多道程序設計」來描述它。事實上,多處理指的是硬體(即 CPU 單元)而不是軟體(即運行的進程)。如果底層硬體提供了多個處理器,那就是多處理。基本方案存在多種變化,例如,一個管芯上有多個內核,或者一個封裝中有多個管芯,或者一個系統中有多個封裝。無論如何,一個系統既可以通過同時運行多個程序來進行多道程序設計,也可以通過擁有多個物理處理器來進行多道處理。

多任務處理

多任務處理與多道程序設計具有相同的含義,但在更一般的意義上,因為它指的是同時運行多個(程序、進程、任務、線程)。當多個任務共享公共處理資源(例如,CPU 和內存)時,該術語用於現代作業系統。在任何時候,CPU 只執行一個任務,而其他任務等待輪到它們執行。當 CPU 被重新分配給另一個任務(即進程或線程上下文切換)時,就實現了並行的錯覺。

多任務處理和多程序設計之間存在細微差別。一個任務在多任務作業系統中,它不是一個完整的應用程式,但當一個進程被劃分為子任務時,它也可以指代「執行線程」。每個較小的任務都不會劫持 CPU,直到它像在舊的多道程序中一樣完成,而是公平共享 CPU 時間,稱為量子。

為了便於記憶,多道程序和多任務作業系統都是(CPU)分時系統。然而,在多道程序(較舊的作業系統)中,一個程序作為一個整體一直運行直到阻塞,而在多任務(現代作業系統)中,時間共享得到了最好的體現,因為每個運行的進程只占用相當一部分 CPU 時間。

多線程

到目前為止,我們已經將多道程序設計作為允許多個程序駐留在主內存中並(顯然)同時運行的一種方式進行了討論。然後,多任務處理是指多個任務通過共享 CPU 時間(顯然)同時運行。最後,多處理描述了具有多個 CPU 的系統。那麼,多線程從何而來?多線程是一種執行模型,允許單個進程在該進程的「上下文」中同時運行多個代碼段(即線程)。您可以將線程視為共享父進程資源但獨立執行的子進程。單個進程的多個線程可以在單 CPU 系統中共享 CPU 或(純粹)在多處理系統中並行運行

為什麼我們需要在單個進程上下文中有多個執行線程?好吧,例如考慮一個 GUI 應用程式,用戶可以在其中發出需要很長時間才能完成的命令(例如,複雜的數學計算)。除非您將此命令設計為在單獨的執行線程中運行,否則您將無法與主應用程式 GUI 交互(例如,更新進度條),因為它在計算進行時將無響應。當然,設計多線程/並發應用程式需要程式設計師處理在開發單線程、順序應用程式時根本不會發生的情況。例如,當兩個或多個線程嘗試訪問和修改共享資源時(競爭條件),程式設計師必須確保這不會使系統處於不一致或死鎖狀態。通常,此線程同步是使用 OS 原語解決的,例如mutexes和sempaphores 。

關鍵字: