您好,登錄后才能下訂單哦!
這篇文章主要介紹了GO并發編程使用方法是什么的相關知識,內容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇GO并發編程使用方法是什么文章都會有所收獲,下面我們一起來看看吧。
指在一臺處理器上同時處理多個任務
此處說的同時,可不是同一個時間一起手拉手做同一件事情
并發是在同一實體上的多個事件,而這個事件在同一時間間隔發生的,同一個時間段,有多個任務執行,可是同一個時間點,只有一個任務在執行
隨著互聯網的普及,互聯網用戶人數原來越多,這對系統的性能帶來了巨大的挑戰。
我們要通過各種方式來高效利用硬件的性能(壓榨),從而提高系統的性能進而提升用戶體驗,提升團隊或者企業的競爭力。
并發是為了解決什么問題?目的是啥?
是充分的利用好處理器的每一個核,以達到最高的處理性能,盡可能的運用好每一塊磚
可是由于現在我們使用的CPU,內存,IO三者之間速度不盡相同
我們為了提高系統性能,計算機系統會將這三者速度進行平衡,以達到最優的效果,都有如下措施:
操作系統增加了進程、線程,以分時復用 CPU,進而均衡 CPU 與 I/O 設備的速度差異;
CPU 增加了緩存,以均衡與內存的速度差異;
編譯程序優化指令執行次序,使得緩存能夠得到更加合理地利用。
說到進程和線程,他們都是干啥的呢,咱們順帶說一下?
進程是程序在操作系統中的一次執行過程
是 系統進行資源分配和調度的一個獨立單位。
線程是進程的一個執行實體
是 CPU 調度和分派的基本單位,它是比進程更小的能獨立運行的基本單位。
一個進程可以創建和撤銷多個線程, 并且同一個進程中的多個線程之間可以并發執行。
講到并發編程不得不說并發和并行有啥區別?是不是總是有小伙伴弄不清楚他們到底是啥區別,好像一樣,又好像不一樣
一言蔽之,區別如下:
并發
多線程程序在一個核的 CPU 上運行
并行
多線程程序在多個核的 CPU 上運行
并發就像多個小伙伴跑接力,同一個時間點只會有一個小伙伴在跑,互相有影響
并行就像是多個小伙伴同一個起點一起跑,互不干擾
我們需要記住一點,再強調一波:
并發不是并行
并發主要由切換時間片來實現"同時"運行
并行則是直接利用多核實現多線程的運行,
在 GO 可以設置使用核數,以發揮多核計算機的能力,不過設置核數都是依賴于硬件的
那么,講到GO的并發編程,就必須上我們的主角,那就是協程
協程是一種程序組件
是由子例程(過程、函數、例程、方法、子程序)的概念泛化而來的
子例程只有一個入口點且只返回一次,而協程允許多個入口點,可以在指定位置掛起和恢復執行。
協程和線程分別有啥特點嘞
協程
獨立的棧空間,共享堆空間,調度由用戶自己控制
本質上有點類似于用戶級線程,這些用戶級線程的調度也是自己實現的。
線程
一個線程上可以跑多個協程,協程是輕量級的線程。
goroutine
奉行通過通信來共享內存
每個一個GO的實例有4~5KB
的棧內存占用,并且由于 GO 實現機制而大幅減少的創建和銷毀開銷
Golang 在語言層面上就支持協程 goroutine
基本協程的原理,實現方式,雖然說,GO中使用協程很方便,可以我們必須要知其然而值其所以然
Goroutine 池
runtime 包的使用
Channel 通道
定時器
并發且安全的鎖
原子操作
select 多路復用
等等...
我們寫C/C++
的時候,我們必然也是要實現并發編程
我們通常需要自己維護一個線程池,并且需要自己去包裝一個又一個的任務,同時需要自己去調度線程執行任務并維護上下文切換
且做線程池的時候,我們需要自己做一個線程管理的角色,靈活動態壓縮和擴容
可是能不能有這樣一種機制,我們只需要定義多個任務,讓系統去幫助我們把這些任務分配到CPU上實現并發執行
GO里面就正好有這樣的機制
goroutine
的概念類似于線程
goroutine
是由Go的運行時(runtime)調度和管理的
Go程序會智能地將 goroutine
中的任務合理地分配給每個CPU
Go 在語言層面已經內置了調度和上下文切換的機制
寫 GO 比較爽的一個地方是:
在GO里面,你不需要去自己寫進程、線程、協程
我們可以使用 goroutine 包
我們需要讓某個任務并發執行的時候,只需要把這個任務包裝成一個函數
專門開啟一個 goroutine 協程 去執行這個函數就可以了 , GO一個協程,很方便
一個 goroutine 必定對應一個函數,可以創建多個 goroutine 去執行相同的函數,只是多個協程都是做同一個事情罷了
我們先來使用一下協程,再來拋磚引玉,適當的分享一下
func Hi() { fmt.Println("this is Hi Goroutine!") } func main() { Hi() fmt.Println("main goroutine!") }
我們一般調用函數是如上這個樣子的,效果如下
this is Hi Goroutine!
main goroutine!
其實我們調用協程的話,也與上述類似
我們可以使用 go 后面加上函數名字,來開辟一個協程,專門做函數需要執行的事情
func main() { go Hi() // 啟動一個goroutine 協程 去執行 Hi 函數 fmt.Println("main goroutine!")
實際效果我們可以看到,程序只打印了 main goroutine!
main goroutine!
在程序啟動的時候,Go 程序就會為 main() 函數創建一個默認的 goroutine 協程
當 main() 函數返回的時候,剛開辟的另外一個 goroutine 協程 就結束了
所有在 main() 函數中啟動的 goroutine 協程 會一同結束,老大死了,其余的傀儡也灰飛煙滅了
我們也可以讓主協程等等一定子協程,待子協程處理完自己的事情,退出后,主協程再自己退出,這和我們寫C/C++的進程 和 線程的時候,類似
簡單的,我們可以使用 time.sleep
函數來讓主協程阻塞等待
我們也可以使用 上述提到的 使用 select{} 來達到目的
當然也有其他的方式,后續文章會慢慢的分享到
那么多個協程又是怎么玩的呢?
我們使用 sync.WaitGroup 來實現goroutine 協程的同步
package main import ( "fmt" "sync" ) var myWg sync.WaitGroup func Hi(i int) { // goroutine 協程 結束就 記錄 -1 defer myWg.Done() fmt.Println("Hello Goroutine! the ", i) } func main() { for i := 0; i < 10; i++ { // 啟動一個goroutine 協程 就記錄 +1 myWg.Add(1) go Hi(i) } // 等待所有記錄 的goroutine 協程 都結束 myWg.Wait() }
會有如下輸出,每一個協程打印的數字并不是按照順序來的:
Hello Goroutine! the 9
Hello Goroutine! the 4
Hello Goroutine! the 2
Hello Goroutine! the 3
Hello Goroutine! the 6
Hello Goroutine! the 5
Hello Goroutine! the 7
Hello Goroutine! the 8
Hello Goroutine! the 1
Hello Goroutine! the 0
還是同樣的, 如果是主協程先退出,那么子協程還行繼續運行嗎?
毋庸置疑,主協程退出,子協程也會跟著退出
分享如下幾個點
GO中的棧是可增長的
一般都有固定的棧內存(通常為2MB),goroutine 的棧不是固定的,goroutine 的棧大小可以擴展到1GB
這就不得不提 GPM
GPM是Go語言運行時(runtime)層面實現的,我們先簡單了解一下GPM分別代表啥
G
就是個 goroutine ,里面除了存放本 goroutine 信息外 還有與所在P的綁定等信息
P
Processor 管理著一組 goroutine 隊列
P 里面會存儲當前 goroutine 運行的上下文環境(函數指針,堆棧地址及地址邊界)
P 會對自己管理的 goroutine 隊列做一些調度(比如把占用CPU時間較長的 goroutine 暫停、運行后續的 goroutine)
當自己的隊列消費完了就去全局隊列里取,如果全局隊列里也消費完了會去其他P的隊列里搶任務。
M(machine)
是 Go 運行時(runtime)對操作系統內核線程的虛擬
M 與內核線程一般是一一映射的關系, 一個 groutine 最終是要放到 M上執行
這里的 P 與 M 一般也是一一對應的
P 管理著一組G 掛載在 M 上運行
當一個 G 長久阻塞在一個 M 上時,runtime 會新建一個M,
阻塞 G 所在的 P 會把其他的 G 掛載在新建的M上
這個時候,當舊的 G 阻塞完成或者認為其已經掛了的話,就會回收舊的 M
還有一點
P 的個數是通過 runtime.GOMAXPROCS
設定(最大256),這個數字也依賴于自己的硬件,在并發量大的時候會增加一些 P 和 M ,但不會太多。
關于“GO并發編程使用方法是什么”這篇文章的內容就介紹到這里,感謝各位的閱讀!相信大家對“GO并發編程使用方法是什么”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。