對多道並行執行的程序來講,有時它要佔用處理器運行,有時要等待傳送信息,當獲得信息後又可繼續執行,一個程序的執行可能受到另外一個程序的約束。因此程序的執行其實是走走停停的,爲了能正確反映程序執行時的活動規律和狀態變化,引進了進程,以便從變化的角度,動態地分析和研究程序的執行。數據庫
用計算機系統來解決某個問題時首先必須編制程序,可把程序看做是具備獨立功能的一組指令的集合,或者說是指出處理器執行操做的步驟。程序的執行必須依賴於一個實體-數據集緩存
還有一個問題就是從程序的角度沒法正確描述程序執行時的狀態。例:只有一個「編譯程序」,同時爲多個用戶服務,有兩個須要編譯的程序甲、乙,假定編譯程序p從a點開始工做,如今正在編譯程序甲,當工做到b點時,須要把中間結果記錄在磁盤上。因而程序p在b 點等待磁盤傳輸信息。這時處理器空閒,這時讓p爲源程序 乙進行編譯,編譯程序仍從a點開始工做。如今 的問題是如何來描述p的狀態?是說「它在b點等侍磁盤傳輸」仍是說「從a點開始執行?多線程
1.進程和線程併發
進程:把一個程序在一個數據集上的一次執行稱爲一個進程spa
(程序是靜止的,進程是動態的。在20世紀80年代,大多數操做系統仍採用進程技術,把進程做爲操做系統的基本組成單位。進程既是資源分配單位,又是調度和執行單位)操作系統
線程:線程是進程中可獨立執行的子任務。線程
(把一個計算問題或一個應用問題做爲一個進程,把該進程中能夠併發執行的各部分分別做爲線程。一個數據庫應用程序的運行建立了一個數據庫進程,用戶要求從數據庫中生產一份工資報表,並將它傳送到一個文件中。用戶在等待報表生成的時候又向數據庫提出一個查詢請求。操做系統把用戶的每個請求(工資單報表,數據庫查詢)分別做爲數據庫進程的一個線程)協程
爲何引入線程?blog
1.每一個進程都要佔用一個進程控制塊和一個私有的主存空間,開銷比較大;進程之間傳遞消息時要從一個工做區傳到另外一個工做區,需專用通訊機制,速度較慢隊列
2.進程增多就增長了進程調度的次數,給調度和控制帶來了複雜性。
在採用線程的操做系統中,進程是資源分配 單位,而線程是調度、執行單位。
協程:獨⽴的棧空間,共享堆空間,調度由⽤戶⾃⼰控制,本質上有點相似於⽤戶級線程,這些⽤戶級線程的調度也是⾃⼰實現的 。⼀個線程上能夠跑多個協程,協程是輕量級的線程。
進程——>一個線程——>單線程程序
進程——>多線程——>多線程程序
2.併發和並行
1)多線程程序在cpu一個核蕊上運行就是併發
2)多線程程序在cpu多個核蕊上運行就是並行
併發是邏輯上的同時發生(simultaneous),而並行是物理上的同時發生。
併發:
並行:
3.用戶空間線程和內核空間線程之間的映射關係
N:1, 1:1和 M:N
N:1是說,多個(N)用戶線程始終在一個內核線程上跑,context上下文切換確實很快,可是沒法真正的利用多核。
1:1是說,一個用戶線程就只在一個內核線程上跑,這時能夠利用多核,可是上下文switch很慢。
M:N是說, 多個goroutine在多個內核線程上跑,這個看似能夠集齊上面二者的優點,可是無疑增長了調度的難度。
4.go的調度器
go 的高度器的內部結構:M P G
圖中看,有2個物理線程M,每個M都擁有一個context(P),每個也都有一個正在運行的goroutine。
P的數量能夠經過GOMAXPROCS()來設置,它其實也就表明了真正的併發度,即有多少個goroutine能夠同時運行。
圖中灰色的那些goroutine並無運行,而是出於ready的就緒態,正在等待被調度。P維護着這個隊列(稱之爲runqueue),
當MO返回時,它必須嘗試取得一個context P來運行goroutine,通常狀況下,它會從其餘的OS線程那裏steal偷一個context過來,