Go 語言比起Java等一個很大的優點就是可以方便地寫並發程式。 Go 語言內建了 goroutine 機制,使用goroutine可以快速地開發並發程序, 更好的利用多核心處理器資源。這篇文章學習 goroutine 的應用及其調度實現。
一、Go語言對同時發生的支援
使用goroutine程式設計 (建議: go影片教學)
使用go 關鍵字用來建立goroutine 。將go宣告放到一個需呼叫的函數之前,在相同位址空間呼叫執行這個函數,這樣函數執行時就會作為一個獨立的並發執行緒。這種線程在Go語言中稱為goroutine。
goroutine的用法如下:
//go 关键字放在方法调用前新建一个 goroutine 并执行方法体 go GetThingDone(param1, param2); //新建一个匿名方法并执行 go func(param1, param2) { }(val1, val2) //直接新建一个 goroutine 并在 goroutine 中执行代码块 go { //do someting... }
因為 goroutine 在多核心 cpu 環境下是並行的。如果程式碼區塊在多個 goroutine 中執行,我們就實作了程式碼並行。
如果需要了解程式的執行情況,怎麼拿到並行的結果呢?需配合使用channel進行。
使用Channel控制並發
Channels用來同步並發執行的函數並提供它們某種傳值交流的機制。
透過channel傳遞的元素類型、容器(或緩衝區)和傳遞的方向由「
可以使用內建函數make分配一個channel:
i := make(chan int) // by default the capacity is 0 s := make(chan string, 3) // non-zero capacity r := make(<-chan bool) // can only read from w := make(chan<- []os.FileInfo) // can only write to
配置runtime.GOMAXPROCS
使用下面的程式碼可以明確的設定是否使用多核來執行並發任務:
runtime.GOMAXPROCS()
GOMAXPROCS的數目根據任務量分配就可以,但是不要大於cpu核數。
配置並行執行比較適合適合於CPU密集型、並行度比較高的情景,如果是IO密集型使用多核心的化會增加cpu切換帶來的效能損失。
了解了Go語言的並發機制,接下來看一下goroutine 機制的具體實作。
二、區別並行與並發
#程式、執行緒與處理器
#在現代作業系統中,執行緒是處理器調度和分配的基本單位,而進程則是作為資源擁有的基本單位。每個進程是由私有的虛擬位址空間、程式碼、資料和其它各種系統資源所組成。執行緒是進程內部的一個執行單元。每一個行程至少有一個主執行線程,它不需要由使用者去主動創建,是由系統自動創建的。用戶根據需要在應用程式中創建其它線程,多個線程並發地運行於同一個進程中。
並行與並發
並行與並發(Concurrency and Parallelism)是兩個不同的概念,理解它們對於理解多執行緒模型非常重要。
在描述程式的並發或並行時,應該說明從進程或執行緒的角度出發。
並發:一個時間段內有很多的執行緒或進程在執行,但何時間點上都只有一個在執行,多個執行緒或進程爭搶時間片輪流執行
#並行:一個時間段和時間點上都有多個執行緒或行程在執行
非並發的程式只有一個垂直的控制邏輯,在任何時刻,程式只會處在這個控制邏輯的某個位置,也就是順序執行。如果一個程式在某一時刻被多個CPU管線同時處理,那麼我們就說這個程式是以並行的形式在運作。
並行需要硬體支持,單核心處理器只能是並發,多核心處理器才能做到並行執行。
並發是並行的必要條件,如果一個程式本身就不是並發的,也就是只有一個邏輯執行順序,那麼我們不可能讓其被並行處理。
並發不是並行的充分條件,一個並發的程序,如果只被一個CPU進行處理(通過分時),那麼它就不是並行的。
舉一個例子,寫一個最簡單的順序結構程式輸出"Hello World",它就是非並發的,如果在程式中增加多線程,每個執行緒都列印一個"Hello World",那麼這個程序就是並發的。如果運行時只給這個程式分配單一CPU,這個並發程式還不是並行的,需要部署在多核心處理器上,才能實現程式的並行。
三、幾個不同的多執行緒模型
#使用者執行緒與核心級執行緒
#執行緒的實作可以分為兩類:使用者級執行緒(User-LevelThread, ULT)和核心級執行緒(Kemel-LevelThread, KLT)。用戶執行緒由使用者程式碼支持,核心執行緒由作業系統核心支援。
多執行緒模型
多執行緒模型即使用者級執行緒和核心級執行緒的不同連接方式。
(1)多對一模型(M : 1)
將多個使用者級執行緒對應到一個核心級線程,執行緒管理在使用者空間完成。在此模式中,使用者級執行緒對作業系統不可見(即透明)。
優點: 這種模型的好處是執行緒上下文切換都發生在使用者空間,避免的模態切換(mode switch),從而對於效能有正面的影響。
缺點:所有的線程基於一個核心調度實體即核心線程,這意味著只有一個處理器可以被利用,在多處理器環境下這是不能夠被接受的,本質上,用戶線程只解決了並發問題,但是沒有解決並行問題。如果線程因為I/O 操作陷入了內核態,內核態線程阻塞等待I/O 數據,則所有的線程都將會被阻塞,用戶空間也可以使用非阻塞而I/O,但是不能避免性能及複雜度問題。
(2) 一對一模型(1:1)
將每個使用者級執行緒對應到一個核心級執行緒。
每個執行緒由核心調度器獨立的調度,所以如果一個執行緒阻塞則不影響其他的執行緒。
優點:在多核心處理器的硬體的支援下,核心空間執行緒模型支援了真正的並行,當一個執行緒被阻塞後,允許另一個執行緒繼續執行,所以並發能力較強。
缺點:每建立一個使用者級執行緒都需要建立一個核心級執行緒與其對應,這樣建立執行緒的開銷比較大,會影響到應用程式的效能。
(3)多對多模型(M : N)
核心執行緒與使用者執行緒的數量比為 M : N,核心使用者空間綜合了前兩種的優點。
這種模型需要核心執行緒調度器和使用者空間執行緒調度器相互操作,本質上是多個執行緒被綁定到了多個核心執行緒上,這使得大部分的執行緒上下文切換都發生在使用者空間,而多個核心執行緒又可以充分利用處理器資源。
四、goroutine機制的調度實現
#goroutine機制實作了M : N的執行緒模型,goroutine機制是協程(coroutine)的一種實現,golang內建的調度器,可以讓多核心CPU中每個CPU執行一個協程。
理解goroutine機制的原理,關鍵在於理解Go語言scheduler的實作。
調度器是如何運作的
Go語言中支撐整個scheduler實作的主要有4個重要結構,分別是M、G、P、Sched, 前三個定義在runtime.h中,Sched定義在proc.c中。
Sched結構就是調度器,它維護有儲存M和G的佇列以及調度器的一些狀態資訊等。
M結構是Machine,系統線程,它由作業系統管理的,goroutine就是跑在M之上的;M是一個很大的結構,裡面維護小物件記憶體cache(mcache)、目前執行的goroutine、隨機數字產生器等等非常多的資訊。
P結構是Processor,處理器,它的主要用途就是用來執行goroutine的,它維護了一個goroutine佇列,也就是runqueue。 Processor是讓我們從N:1調度到M:N調度的重要部分。
G是goroutine實作的核心結構,它包含了堆疊,指令指針,以及其他對調度goroutine很重要的訊息,例如其阻塞的channel。
Processor的數量是在啟動時被設定為環境變數GOMAXPROCS的值,或是透過執行時間呼叫函數GOMAXPROCS()來設定。 Processor數量固定意味著任意時刻只有GOMAXPROCS個執行緒在執行go程式碼。
我們分別用三角形,矩形和圓形表示Machine Processor和Goroutine。
在單核心處理器的場景下,所有goroutine運行在同一個M系統執行緒中,每一個M系統執行緒維護一個Processor,任何時刻,一個Processor中只有一個goroutine,其他goroutine在runqueue中等待。一個goroutine運行完自己的時間片後,讓出上下文,回到runqueue。多核心處理器的場景下,為了執行goroutines,每個M系統執行緒會持有一個Processor。
在正常情況下,scheduler會按照上面的流程進行調度,但是執行緒會發生阻塞等情況,看一下goroutine對執行緒阻塞等的處理。
線程阻塞
當正在運行的goroutine阻塞的時候,例如進行系統調用,會再創建一個系統線程(M1),當前的M線程放棄了它的Processor,P轉到新的線程中去運行。
runqueue執行完成
當其中一個Processor的runqueue為空,沒有goroutine可以排程。它會從另外一個上下文偷取一半的goroutine。
五、對並發實現的進一步思考
Go語言的並發機制還有很多值得探討的,如Go語言和Scala並發實作的不同,Golang CSP 和Actor模型的比較等。
了解並發機制的這些實現,可以幫助我們更好的進行並發程序的開發,實現效能的最優化。
關於三種多執行緒模型,可以關註一下Java語言的實作。
我們知道Java透過JVM封裝了底層作業系統的差異,而不同的作業系統可能使用不同的執行緒模型,例如Linux和windows可能使用了一對一模型,solaris和unix某些版本可能使用多對多模型。 JVM規格裡沒有規定多執行緒模型的具體實現,1:1(核心執行緒)、N:1(使用者狀態執行緒)、M:N(混合)模型的任何一種都可以。談到Java語言的多執行緒模型,需要針對具體JVM實現,例如Oracle/Sun的HotSpot VM,預設使用1:1執行緒模型。
以上是Go語言並發機製圖文詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

Golang和C 在性能競賽中的表現各有優勢:1)Golang適合高並發和快速開發,2)C 提供更高性能和細粒度控制。選擇應基於項目需求和團隊技術棧。

Golang適合快速開發和並發編程,而C 更適合需要極致性能和底層控制的項目。 1)Golang的並發模型通過goroutine和channel簡化並發編程。 2)C 的模板編程提供泛型代碼和性能優化。 3)Golang的垃圾回收方便但可能影響性能,C 的內存管理複雜但控制精細。

goimpactsdevelopmentpositationality throughspeed,效率和模擬性。 1)速度:gocompilesquicklyandrunseff,IdealforlargeProjects.2)效率:效率:ITScomprehenSevestAndardArdardArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdEcceSteral Depentencies,增強的Depleflovelmentimency.3)簡單性。

C 更適合需要直接控制硬件資源和高性能優化的場景,而Golang更適合需要快速開發和高並發處理的場景。 1.C 的優勢在於其接近硬件的特性和高度的優化能力,適合遊戲開發等高性能需求。 2.Golang的優勢在於其簡潔的語法和天然的並發支持,適合高並發服務開發。

Golang在实际应用中表现出色,以简洁、高效和并发性著称。1)通过Goroutines和Channels实现并发编程,2)利用接口和多态编写灵活代码,3)使用net/http包简化网络编程,4)构建高效并发爬虫,5)通过工具和最佳实践进行调试和优化。

Go語言的核心特性包括垃圾回收、靜態鏈接和並發支持。 1.Go語言的並發模型通過goroutine和channel實現高效並發編程。 2.接口和多態性通過實現接口方法,使得不同類型可以統一處理。 3.基本用法展示了函數定義和調用的高效性。 4.高級用法中,切片提供了動態調整大小的強大功能。 5.常見錯誤如競態條件可以通過gotest-race檢測並解決。 6.性能優化通過sync.Pool重用對象,減少垃圾回收壓力。

Go語言在構建高效且可擴展的系統中表現出色,其優勢包括:1.高性能:編譯成機器碼,運行速度快;2.並發編程:通過goroutines和channels簡化多任務處理;3.簡潔性:語法簡潔,降低學習和維護成本;4.跨平台:支持跨平台編譯,方便部署。

關於SQL查詢結果排序的疑惑學習SQL的過程中,常常會遇到一些令人困惑的問題。最近,筆者在閱讀《MICK-SQL基礎�...


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

Dreamweaver Mac版
視覺化網頁開發工具

PhpStorm Mac 版本
最新(2018.2.1 )專業的PHP整合開發工具

SublimeText3 英文版
推薦:為Win版本,支援程式碼提示!

DVWA
Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

mPDF
mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),