摘要:每個進程的第一個線程都會隨著該進程的啟動而被創建,它們可以被稱為其所屬進程的主線程。因此,線程也被稱為輕量級進程。與進程調度類似,在線程之間快速切換,制造了線程并行運行的假象。也就是說,線程之間是沒有保護的。其中的指代的就是系統級線程。
其實,在早期計算機并沒有包含操作系統,這個時候,這個計算機只跑一個程序,這個程序獨享計算機的所有資源,這個時候不存在什么并發問題,但是對計算機的資源來說,確實是一種浪費。早期編程都是基于單進程來進行,隨著計算機技術的發展,于是,操作系統出現了,操作系統改變了這種現狀,讓計算機可以運行多個程序,并且不同的程序占用獨立的計算機資源,如內存,CPU等。
操作系統出現后:
當計算機從單程序變成多程序之后,這個時候又發展出了多線程,線程是進程里面的每個執行控制流,或叫執行路線。如果沒有明確的協同機制,那么每個線程將獨立運行,共享著進程的內存及CPU資源,多進程多線程之間雖然讓多任務并行處理的能力大大提升,但是本質上還是分時系統,并不是時間上真正的并行,解決這個問題的方式顯而易見,就是讓多個CPU能夠同時計算任務,從而實現真正意義上的多任務并行。
并發可以滿足多任務任務需求,比如一邊寫代碼一邊聽音樂,即使編寫多線程程序具有挑戰性,但它仍在使用中,是因為它可以帶來如下的好處:
單核的 CPU 一次只能執行一個任務,想要實現多任務,需要把 CPU 的運行時間切成一段一段的時間片,每個時間片運行一個程序,循環的分配時間片給不同的應用程序,由于時間片非常的短,在用戶看來,就像是多個任務同時在運行。
進程的調度
在計算機的世界里,內核把CPU的執行時間切分成許多時間片,比如1秒鐘可以切分為100個10毫秒的時間片,每個時間片再分發給不同的進程,通常,每個進程需要多個時間片才能完成一個請求。這樣,雖然微觀上,比如說就這10毫秒時間CPU只能執行一個進程,但宏觀上1秒鐘執行了100個時間片,于是每個時間片所屬進程中的請求也得到了執行,這就實現了請求的并發執行。
流水線
CPU就好像一個流水線上的工人,不斷的處理流水線上的各種信息包裹,打開包裹讀取指令并執行,遇到執行慢的IO調用(或執行時間片結束)則會暫時把它放到等候區,繼續處理流水線上下一個等待處理的包裹。等候區有很多這樣的包裹,等待著系統的IO執行完成,當IO調用結束后,又開始進入到等待處理隊列。
進程的缺點:在操作系統中,每個進程的內存空間都是獨立的,這樣用多進程實現并發就有兩個缺點:一是內核的管理成本高,二是無法簡單地通過內存同步數據,很不方便于是多線程模式就出現了。
線程,是操作系統能夠進行運算調度的最小單位。它被包含在進程之中,是進程中的實際運作單位。一條線程指的是進程中一個單一順序的控制流,一個進程中可以并發多個線程,每條線程并行執行不同的任務。線程總是在進程之內的。一個進程至少會包含一個線程。
如果一個進程只包含了一個線程,那么它里面的所有代碼都只會被串行地執行。每個進程的第一個線程都會隨著該進程的啟動而被創建,它們可以被稱為其所屬進程的主線程。相對應的,如果一個進程中包含了多個線程,那么其中的代碼就可以被并發地執行。除了進程的第一個線程之外,其他的線程都是由進程中已存在的線程創建出來的。所以,線程可以通過共享內存地址空間,解決內核的管理成本、內存同步數據的問題。
線程
由于線程運行的本質就是函數運行,函數運行時信息是保存在棧幀中的,因此 每個線程都有自己獨立的、私有的棧區。
代碼區
進程地址空間中的代碼區,這里保存的是什么呢?從名字中有的同學可能已經猜到了,沒錯,這里保存的就是我們寫的代碼,更準確的是 編譯后的可執行機器指令。
heap
heap很顯然,只要知道變量的地址,也就是指針,任何一個線程都可以訪問指針指向的數據,因此堆區也是線程共享的屬于進程的資源。
stack
通常來說棧區是線程私有,既然有通常就有不通常的時候,不通常是因為不像進程地址空間之間的嚴格隔離,線程的棧區沒有嚴格的隔離機制來保護,因此 如果一個線程能拿到來自另一個線程棧幀上的指針,那么該線程就可以改變另一個線程的棧區,也就是說這些線程可以任意修改本屬于另一個線程棧區中的變量。
線程的調度與缺點:
在同一個進程中并行運行多個線程,是對在同一臺計算機上并行運行多個進程的模擬。因此,線程也被稱為輕量級進程。與進程調度類似,CPU在線程之間快速切換,制造了線程并行運行的假象。由于各個線程都可以訪問進程地址空間的每一個內存地址,所以一個線程可以讀、寫,甚至清除另一個線程的堆棧。也就是說,線程之間是沒有保護的。但要注意的是,每個線程都有自己的堆棧、程序計數器、寄存器等信息,這些不是共享的。
上下文切換
線程的切換是由內核控制的,什么時候會切換線程呢?不只時間片用盡,當調用阻塞方法時,內核為了CPU 充分工作,也會切換到其他線程執行。一次上下文切換的成本在幾十納秒到幾微秒間,當線程繁忙且數量眾多時,這些切換會消耗絕大部分的CPU運算能力。
協程就是用戶態的線程。通常創建協程時,會從進程的堆中分配一段內存作為協程的棧。線程的棧有8MB,而協程棧的大小通常只有幾十 KB。而且,C庫內存池也不會為協程預分配內存,它感知不到協程的存在。這樣,更低的內存占用空間為高并發提供了保證,畢竟十萬并發請求,就意味著10萬個協程。
兩級線程模型中用戶線程與內核線程是一對一關系
每個協程有獨立的棧,而棧既保留了變量的值,也保留了函數的調用關系、參數和返回值,CPU中的棧寄存器SP指向了當前協程的棧,而指令寄存器IP保存著下一條要執行的指令地址。因此,從協程1切換到協程2時,首先要把SP、IP寄存器的值為線程1保存下來,再從內存中找出協程2上一次切換前保存好的寄存器值,寫入CPU的寄存器,這樣就完成了協程切換。
在GO語言中,語言的運行時系統會幫助我們自動地創建和銷毀系統級的線程。這里的系統級線程指的就是我們剛剛說過的操作系統提供的線程。而對應的用戶級協程指的是架設在系統級線程之上的,由我們編寫的程序完全控制的代碼執行流程。用戶級協程的創建、銷毀、調度、狀態變更以及其中的代碼和數據都完全需要我們的程序自己去實現和處理。這帶來了很多優勢,比如,因為它們的創建和銷毀并不用通過操作系統去做,所以速度會很快,又比如,由于不用等著操作系統去調度它們的運行,所以往往會很容易控制并且可以很靈活。
其中的M指代的就是系統級線程。而P指的是一種可以承載若干個G,且能夠使這些G適時地與M進行對接,并得到真正運行的中介。
當一個正在與某個M對接并運行著的G,需要因某個事件(比如等待 I/O或鎖的解除)而暫停運行的時候,調度器總會及時地發現,并把這個G與那個M分離開,以釋放計算資源供那些等待運行的G使用。而當一個G需要恢復運行的時候,調度器又會盡快地為它尋找空閑的計算資源(包括M)并安排運行。另外,當M不夠用時,調度器會幫我們向操作系統申請新的系統級線程,而當某個M已無用時,調度器又會負責把它及時地銷毀掉。所以Go程序總是能高效地利用操作系統和計算機資源。程序中的所有goroutine也都會被充分地調度,其中的代碼也都會被并發地運行,即使這樣的goroutine有數以十萬計,也仍然可以如此。
進程、線程、協程的區別主要體現在執行體的顆粒度上。最初的執行體任務比較簡單,用一個進程就能滿足需求,隨著執行體做的事情越來越復雜,就出現了進程內多任務的需求。
進程和線程都屬于系統級的任務,切換進程、線程都需要經歷用戶態躍遷內核態,切換成功后再由內核態切回用戶態。
為了實現高性能,我們應該盡可能的減少異步線程。因為協程沒有局部存儲,相對來說空間成本就小很多,同時它又能滿足需求。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/125630.html
摘要:因為多線程競爭鎖時會引起上下文切換。減少線程的使用。舉個例子如果說服務器的帶寬只有,某個資源的下載速度是,系統啟動個線程下載該資源并不會導致下載速度編程,所以在并發編程時,需要考慮這些資源的限制。 最近私下做一項目,一bug幾日未解決,總惶恐。一日頓悟,bug不可怕,怕的是項目不存在bug,與其懼怕,何不與其剛正面。 系列文章傳送門: Java多線程學習(一)Java多線程入門 Jav...
摘要:相比與其他操作系統包括其他類系統有很多的優點,其中有一項就是,其上下文切換和模式切換的時間消耗非常少。因為多線程競爭鎖時會引起上下文切換。減少線程的使用。很多編程語言中都有協程。所以如何避免死鎖的產生,在我們使用并發編程時至關重要。 系列文章傳送門: Java多線程學習(一)Java多線程入門 Java多線程學習(二)synchronized關鍵字(1) java多線程學習(二)syn...
摘要:現在在后端業務開發編程方面,技術力量強的團隊已經開始將技術棧從同步模式切換為異步了。使用這些技術方案是無法兼容已有程序的。影響了異步回調技術棧的普及。將會成為未來后端開發領域的主流技術方案。 今天太忙,少寫一點,后面再補充。 異步模式 Go 語言越來越熱門,很多大型互聯網公司后端正在轉向 GO 。Java 圈知名的服務化框架 Dubbo 也宣布轉型異步模式。這是一個大趨勢,異步模式已經...
摘要:本文介紹和點評上的等并發編程模型。異步更適合并發編程。同步使線程阻塞,導致等待。基本模型這是最簡單的模型,創建線程來執行一個任務,完畢后銷毀線程。響應式編程是一種面向數據流和變化傳播的編程模式。起源于電信領域的的編程模型。 本文介紹和點評JVM上的Thread, Thread Pool, Future, Rx, async-await, Fiber, Actor等并發編程模型。本人經驗...
摘要:本文介紹和點評上的等并發編程模型。異步更適合并發編程。同步使線程阻塞,導致等待。基本模型這是最簡單的模型,創建線程來執行一個任務,完畢后銷毀線程。響應式編程是一種面向數據流和變化傳播的編程模式。起源于電信領域的的編程模型。 本文介紹和點評JVM上的Thread, Thread Pool, Future, Rx, async-await, Fiber, Actor等并發編程模型。本人經驗...
閱讀 3733·2023-01-11 11:02
閱讀 4244·2023-01-11 11:02
閱讀 3050·2023-01-11 11:02
閱讀 5180·2023-01-11 11:02
閱讀 4733·2023-01-11 11:02
閱讀 5533·2023-01-11 11:02
閱讀 5313·2023-01-11 11:02
閱讀 3986·2023-01-11 11:02