并發(fā)與并行
并發(fā):同一時間段內(nèi)執(zhí)行多個任務
并行:同一時刻執(zhí)行多個任務
? ? ? ? Go語言的并發(fā)通過goroutine實現(xiàn)。goroutine類似于線程,屬于用戶態(tài)的線程,我們可以根據(jù)需要創(chuàng)建成千上萬個goroutine并發(fā)工作。goroutine是由Go語言的運行時(runtime)調(diào)度完成,而線程是由操作系統(tǒng)調(diào)度完成。
????????Go語言還提供channel在多個goroutine間進行通信。goroutine和channel是 Go 語言秉承的 CSP并發(fā)模式的重要實現(xiàn)基礎。
goroutine
????????Go語言中的goroutine是,程序員只需要定義很多個任務,讓系統(tǒng)去幫助我們把這些任務分配到CPU上實現(xiàn)并發(fā)執(zhí)行的一種機制,goroutine的概念類似于線程,但?goroutine是由Go的運行時(runtime)調(diào)度和管理的。Go程序會智能地將 goroutine 中的任務合理地分配給每個CPU。Go語言之所以被稱為現(xiàn)代化的編程語言,就是因為它在語言層面已經(jīng)內(nèi)置了調(diào)度和上下文切換的機制。
????????在Go語言編程中你不需要去自己寫進程、線程、協(xié)程,你的技能包里只有一個技能–goroutine,當你需要讓某個任務并發(fā)執(zhí)行的時候,你只需要把這個任務包裝成一個函數(shù),開啟一個goroutine去執(zhí)行這個函數(shù)就可以了,就是這么簡單粗暴。
channel
? ??????Go語言的并發(fā)模型是CSP,提倡通過通信共享內(nèi)存而不是通過共享內(nèi)存而實現(xiàn)通信。
????????如果說goroutine是Go程序并發(fā)的執(zhí)行體,channel就是它們之間的連接。channel是可以讓一個goroutine發(fā)送特定值到另一個goroutine的通信機制。
? ? ? ? Go 語言中的通道是一種特殊的類型。通道像一個傳送帶或者隊列,總是遵循先入先出(FIFO)的規(guī)則,保證收發(fā)數(shù)據(jù)的順序。每一個通道都是一個具體類型的導管,也就是聲明channel的時候需要為其指定元素類型。
select多路復用
????????select的使用類似于switch語句,它有一系列case分支和一個默認的分支。每個case會對應一個通道的通信(接收或發(fā)送)過程。select會一直等待,直到某個case的通信操作完成時,就會執(zhí)行case分支對應的語句。
????????????????使用select語句能提高代碼的可讀性。
????????????????????????可處理一個或多個channel的發(fā)送/接收操作。
????????????????????????如果多個case同時滿足,select會隨機選擇一個。
????????????????????????對于沒有case的select{}會一直等待,可用于阻塞main函數(shù)。
并發(fā)安全和鎖
????????有時候在Go代碼中可能會存在多個goroutine同時操作一個資源(臨界區(qū)),這種情況會發(fā)生競態(tài)問題(數(shù)據(jù)競態(tài))。
互斥鎖
????????互斥鎖是一種常用的控制共享資源訪問的方法,它能夠保證同時只有一個goroutine可以訪問共享資源。Go語言中使用sync包的Mutex類型來實現(xiàn)互斥鎖。?
讀寫互斥鎖
????????讀寫鎖在Go語言中使用sync包中的RWMutex類型。
????????讀寫鎖分為兩種:讀鎖和寫鎖。當一個goroutine獲取讀鎖之后,其他的goroutine如果是獲取讀鎖會繼續(xù)獲得鎖,如果是獲取寫鎖就會等待;當一個goroutine獲取寫鎖之后,其他的goroutine無論是獲取讀鎖還是寫鎖都會等待。