我已經理解了併發和並行的區別

来源:https://www.cnblogs.com/f-ck-need-u/archive/2019/07/10/11161481.html
-Advertisement-
Play Games

理解併發、並行的例子 先舉例子來理解這2個概念的區別。 老師讓兩個同學去辦公室談話。如果這兩同學(進程)是併列跨過辦公室門(CPU)的,那麼就是並行。如果同學A先進同學B後進入(或者先B後A),或者兩人併列同時進入,但是在辦公室外的路人甲(用戶)看來,同學A和同學B同時都在辦公室內,這是併發。 其實 ...


理解併發、並行的例子

先舉例子來理解這2個概念的區別。

老師讓兩個同學去辦公室談話。如果這兩同學(進程)是併列跨過辦公室門(CPU)的,那麼就是並行。如果同學A先進同學B後進入(或者先B後A),或者兩人併列同時進入,但是在辦公室外的路人甲(用戶)看來,同學A和同學B同時都在辦公室內,這是併發。

其實這個例子不合理,因為真正的並行是多核CPU下的概念,但上面這個簡單的例子非常有助於理解。

如果舉例要精確一點,那麼大概是這樣的:進辦公室有兩個門(兩CPU),如果兩同學分別從不同的門進入,不管先後性,兩者互相獨立,那麼是並行;如果兩同學不管以什麼方式進入,在路人甲看來,他兩同時都在辦公室內,就是併發。

我不信到現在還不理解併發和並行。

併發和並行的理論性解釋

為什麼操作系統上可以同時運行多個程式而用戶感覺不出來?

這是因為無論是單CPU還是多CPU,操作系統都營造出了可以同時運行多個程式的假象。實際的過程操作系統對進程的調度以及CPU的快速上下文切換實現的:每個進程執行一會就先停下來,然後CPU切換到下個被操作系統調度到的進程上使之運行。因為切換的很快,使得用戶認為操作系統一直在服務自己的程式。

再來解釋併發就容易理解多了。

併發(concurrent)指的是多個程式可以同時運行的現象,更細化的是多進程可以同時運行或者多指令可以同時運行。但這不是重點,在描述併發的時候也不會去扣這種字眼是否精確,併發的重點在於它是一種現象。併發描述的是多進程同時運行的現象。但實際上,對於單核心CPU來說,同一時刻只能運行一個進程。所以,這裡的"同時運行"表示的不是真的同一時刻有多個進程運行的現象,這是並行的概念,而是提供一種功能讓用戶看來多個程式同時運行起來了,但實際上這些程式中的進程不是一直霸占CPU的,而是執行一會停一會。

所以,併發和並行的區別就很明顯了。它們雖然都說是"多個進程同時運行",但是它們的"同時"不是一個概念。並行的"同時"是同一時刻可以多個進程在運行(處於running),併發的"同時"是經過上下文快速切換,使得看上去多個進程同時都在運行的現象,是一種OS欺騙用戶的現象

實際上,當程式中寫下多進程或多線程代碼時,這意味著的是併發而不是並行。併發是因為多進程/多線程都是需要去完成的任務,不並行是因為並行與否由操作系統的調度器決定,可能會讓多個進程/線程被調度到同一個CPU核心上。只不過調度演算法會儘量讓不同進程/線程使用不同的CPU核心,所以在實際使用中幾乎總是會並行,但卻不能以100%的角度去保證會並行。也就是說,並行與否程式員無法控制,只能讓操作系統決定

再次註明,併發是一種現象,之所以能有這種現象的存在,和CPU的多少無關,而是和進程調度以及上下文切換有關的。

理解了概念,再來深入擴展下。

串列、並行和併發

任務描述

如圖:

1559104246414

任務是將左邊的一堆柴全部搬到右邊燒掉,每個任務包括三個過程:取柴,運柴,放柴燒火。

這三個過程分別對應一個函數:

func get { geting }
func carry { carrying }
func unload { unloading }

串列模式

串列表示所有任務都一一按先後順序進行。串列意味著必須先裝完一車柴才能運送這車柴,只有運送到了,才能卸下這車柴,並且只有完成了這整個三個步驟,才能進行下一個步驟

和稍後所解釋的並行相對比,串列是一次只能取得一個任務,並執行這個任務

假設這堆柴需要運送4次才能運完,那麼當寫下的代碼類似於下麵這種時,那麼就是串列非併發的模式:

for(i=0;i<4;i++){
    get()
    carry()
    unload()
}

或者,將三個過程的代碼全部集中到一個函數中也是如此:

func task {
    geting
    carrying
    unloading
}

for(i=0;i<4;i++){
    task()
}

這兩種都是串列的代碼模式。畫圖描述:

1559105891580

並行模式

並行意味著可以同時取得多個任務,並同時去執行所取得的這些任務。並行模式相當於將長長的一條隊列,劃分成了多條短隊列,所以並行縮短了任務隊列的長度

正如前面所舉的兩同學進辦公室的例子,串列的方式下,必須1個同學進入後第二個同學才進入,隊列長度為2,而並行方式下可以同時進入,隊列長度減半了。

並行的效率從代碼層次上強依賴於多進程/多線程代碼,從硬體角度上則依賴於多核CPU

對於單進程/單線程,由於只有一個進程/線程在執行,所以儘管同時執行所取得的多個任務,但實際上這個進程/線程是不斷的在多任務之間切換,一會執行一下這個,一會執行一下那個,就像是一個人在不同地方之間來回奔波。所以,單進程/線程的並行,效率比串列更低。

對於多進程/多線程,各進程/線程都可以執行各自所取得的任務,這是真正的並行。

但是,還需要考慮硬體層次上CPU核心數,如果只有單核CPU,那麼在硬體角度上這單核CPU一次也只能執行一個任務,上面多進程/多線程的並行也並非真正意義上的並行。只有多核CPU,並且多進程/多線程並行,才是真正意義上的並行。

如下圖,是多進程/多線程(2個工作者)的並行:

1559106284586

併發

併發表示多個任務同時都要執行的現象,更詳細的概念前面已經說面的夠具體了。

其實,很多場景下都會使用併發的概念。比如同時500個http請求涌向了web伺服器,比如有時候說併發數是1000等。

有時候也將併發當成任務,比如500併發數意味著500個任務,表示的是在一個特定的時間段內(約定俗成的大家認為是1秒)可以完成500個任務。這500個任務可以是單進程/單線程方式處理的,這時表示的是併發不並行的模式(coroutine就是典型的併發不並行),即先執行完一個任務後才執行另一個任務,也可以是多進程/多線程方式處理的,這時表示的是併發且並行模式。

要解決大併發問題,通常是將大任務分解成多個小任務。很典型的一個例子是處理客戶端的請求任務,這個大任務裡面包含了監聽並建立客戶端的連接、處理客戶端的請求、響應客戶端。但基本上所有這類程式,都將這3部分任務分開了:在執行任何一個小任務的時候,都可以通過一些手段使得可以執行其它小任務,比如在處理請求的時候,可以繼續保持監聽狀態。

由於操作系統對進程的調度是隨機的,所以切分成多個小任務後,可能會從任一小任務處執行。這可能會出現一些現象:

  • 可能出現一個小任務執行了多次,還沒開始下個任務的情況。這時一般會採用隊列或類似的數據結構來存放各個小任務的成果。比如負責監聽的進程已經執行了多次,建立了多個連接,但是還沒有調度到處理請求的進程去處理任何一個請求。

  • 可能出現還沒準備好第一步就執行第二步的可能。這時,一般採用多路復用或非同步的方式,比如只有準備好產生了事件通知才執行某個任務。比如還沒有和任何一個客戶端建立連接時,就去執行了處理請求的進程。
  • 可以多進程/多線程的方式並行執行這些小任務。也可以單進程/單線程執行這些小任務,這時很可能要配合多路復用才能達到較高的效率

看圖非常容易理解:

1559106934889

上圖中將一個任務中的三個步驟取柴、運柴、卸柴劃分成了獨立的小任務,有取柴的老鼠,有運柴的老鼠,有卸柴燒火的老鼠。

如果上圖中所有的老鼠都是同一隻,那麼是串列併發的,如果是不同的多只老鼠,那麼是並行併發的

總結

並行和串列:

  • 串列:一次只能取得一個任務並執行這一個任務
  • 並行:可以同時通過多進程/多線程的方式取得多個任務,並以多進程或多線程的方式同時執行這些任務
  • 註意點:
    • 如果是單進程/單線程的並行,那麼效率比串列更差
    • 如果只有單核cpu,多進程並行並沒有提高效率
    • 從任務隊列上看,由於同時從隊列中取得多個任務並執行,相當於將一個長任務隊列變成了短隊列

併發:

  • 併發是一種現象:同時運行多個程式或多個任務需要被處理的現象
  • 這些任務可能是並行執行的,也可能是串列執行的,和CPU核心數無關,是操作系統進程調度和CPU上下文切換達到的結果
  • 解決大併發的一個思路是將大任務分解成多個小任務:
    • 可能要使用一些數據結構來避免切分成多個小任務帶來的問題
    • 可以多進程/多線程並行的方式去執行這些小任務達到高效率
    • 或者以單進程/單線程配合多路復用執行這些小任務來達到高效率

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 效果如圖: js代碼: $("#tdg").datagrid({ width: 200, url: "/Laboratory/ShipmentRegister/LoadData", queryParams: { auvp: 'r', condition: " and State='0' " }, s ...
  • 在View中完成數據篩選,無需改變數據源的內容,這樣就不必擔心在其它地方也使用這個數據源。 從路由事件 TextBoxBase.TextChanged 中獲取輸入的文本,並設置視圖的過濾器就可以了。 CollectionViewSource.GetDefaultView 方法是返回一個 IColle ...
  • 小白開學Asp.Net Core《五》 —— 使用.Net Core MVC Filter 一、簡介 今天在項目(https://github.com/AjuPrince/Aju.Carefree)做登陸許可權時,用到了Filter,現將Filer的使用做以下記錄。 二、Filter 簡介 Filte ...
  • 概述: 1、構造函數和析構函數是類中比較特殊的兩種成員函數,分別用來對對象進行初始化和回收對象資源。 構造函數—————對象初始化!!! 析構函數—————回收對象資源!! 2、對象的生命周期從構造函數開始,從析構函數結束。如果一個類含有構造函數,在實例化該類的對象時就會被調用。如果含有析構函數,則 ...
  • 服務端代碼[控制台示例] Socket 相關類 客戶端連接[網頁測試] <!DOCTYPE html WebSockets客戶端示例 var webSocket; function connect() { try { var readyState = new Array("正在連接","已建立連接" ...
  • 需要兩台伺服器,一臺域控制器,一臺部署Office Online Server https://docs.microsoft.com/zh-cn/officeonlineserver/office-online-server 概述 使用office online功能,首先需要的是2台主機,其中一臺是 ...
  • 相信.Net開發人員都想能夠熟記各種VS快捷鍵以提高平時開發的效率,但苦於記憶能力太差而快捷鍵又特別多,特別煩,所以作罷! 下麵我將簡單介紹一下我記憶VS快捷鍵的一些方法,希望對大家有所幫助。 1、視窗快捷鍵 (大家有沒有發現但凡跟視窗掛上鉤的快捷鍵當中都有一個W,那是因為W代表Windows也就是 ...
  • 回到目錄 在這一小節中,我們詳細分析BJT的共基組態電路。在BJT的共基組態中,“輸入埠”和“輸出埠”共用BJT的基極端子(故稱為“共基”),形成一個雙埠網路,如下圖所示: 圖 3-3.01 無論是npn型還是pnp型,下式總是成立的,這是我們後面分析的基礎公式: 在後面的分析中,我們都將以n ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...