一、前言
很多人會把並發與並行的概念弄混,有時候說並發有時候說並行,那麽兩者究竟有啥區別那,本節我們就來澄清下兩者概念。
二、並發與並行
首先我們先看下什麽是進程,比如你打開的微信app就是一個進程、打開的手淘App、記事本程序就是一個進程,在高級編程語言中你啓動main函數運行後其實也啓動了一個進程。
進程(Process)是計算機中的程序在某數據集合上的一次運行活動,是系統進行資源分配和調度的基本單位,也就是說操作系統是以進程爲單位進行資源分配的,但是 CPU 這個資源卻比較特殊,CPU 的分配是以線程爲單位的,這是因爲具體占用 CPU 運行的是進程中的線程。一個進程中至少有一個線程,比如啓動main函數運行的時候,main函數所在線程就是該進程的主線程,在go中main函數所在線程的生命周期等于進程的生命周期,當main函數所在線程運行結束後,進程就退出了。
如上圖進程中包含進程控制塊(PCB)和用戶地址空間和很多線程:
- 其中PCB用來保存進程的控制信息,比如每個pc上全局唯一的進程編號,進程的上下信息(當進程執行上下文切換時候要保存當前進程的上下文信息),控制信息(比如用來管理調度的進程的狀態、進程間通信的信號量或消息隊列信息、cpu資源的使用情況等)
- 用戶地址空間則用來保存進程運行時需要的代碼和數據等信息。
- 每個進程中可以有多個線程,每個線程有自己的用戶棧資源,用于存儲該線程的局部變量,這些局部變量是該線程私有的,其它線程是訪問不了的,另外棧還用來存在當前線程的函數調用棧幀信息,用戶棧用來存放用戶程序執行的一些信息,系統棧用來存放native調用的執行信息。
並發是指同一個時間段內多個任務同時交叉執行,並且都沒有執行結束,而並行是說在單位時間內多個任務同時在執行,並發任務強調在一個時間段內同時執行,而一個時間段有多個單位時間累積而成,所以說並發的多個任務在單位時間內不一定同時在執行。
在單個cpu的時代多個任務同時運行都是並發,這是因爲cpu同時只能執行一個任務,單個cpu時代多任務是共享一個cpu的,當一個任務占用cpu運行時候,其它任務就會被挂起,當占用cpu的任務時間片用完後,會把cpu讓給其它任務來使用,所以在單cpu時代多線程編程是意義不大,並且線程間頻繁的上下文切換還會帶來開銷。
如下圖單個cpu上運行兩個線程,可知線程A和B是輪流使用cpu進行任務處理的,也就是同時CPU只在執行一個線程上面的任務,當前線程A的時間片用完後會進行線程上下文切換,也就是保存當前線程的執行線程,然後切換線程B占用cpu運行任務,線程A和線程B走走停停、交叉運行的,我們就說線程A和線程B是並發運行的:
如下圖雙cpu時候,線程A和線程B各自在自己的CPU上執行任務,實現了真正的並行運行。
而在多線程編程實踐中線程的個數往往多于CPU的個數,所以平時都是稱多線程並發編程而不是多線程並行編程。
三、爲什麽要多線程並發編程
隨著多核CPU時代的到來,打破了單核CPU對多線程效能的限制,多個CPU意味著每個線程可以使用自己的CPU運行,這減少了線程上下文切換的開銷,並且隨著對應用系統性能和吞吐量的要求提高,還有海量數據處理和請求的要求,都對高並發編程有著迫切的需求。
四、總結
並發強調多個任務在一個時間段內走走停停,交叉運行,並不要求多個任務在單位時間內同時運行,例如在單cpu上運行多個任務或者在任務數大于cpu個數時候使用分時複用cpu策略運行任務就是並發運行;而並行則強調多個任務同時運行。