本文目錄一覽:
golang多線程簡單邏輯
實現指定個核心最大化使用,比如核心總數減一。
必要的庫。
要使用的cpu數量,建議不全使用。
建立管道。
聲明使用的cpu數。
建立互斥關係,本例中主要為了實現所有線程執行完後再執行後續程序。
創建cpu數減1個線程
後面每個任務結束時要done一個wg,這裡根據具體情況加,是循環就在每個循環里加,保證後面能全部done即可
沒有緩衝的、阻塞式的往管道傳遞字符串。
Wait是等所有線程都執行完,即增加的數字被全done掉。
關閉管道。
假設已有的函數是ReadLogs,在它的基礎上加個Wg加函數名的新函數,我覺得這種方式不改變原有的,比較舒服。
大意是:循環從管道讀取字符串,讀不到了就跳出循環。
每個ReadLogs()之後加一個wg.Done(),相當於計數減一。
ReadLogs()就是要執行的任務,不再解釋。
就是開指定個線程。
管道阻塞傳值。
wg同步。
WgReadLogs循環接收。
Go語言WaitGroup使用時需要注意什麼
WaitGroup在go語言中,用於線程同步,單從字面意思理解,wait等待的意思,group組、團隊的意思,WaitGroup就是指等待一組,等待一個系列執行完成後才會繼續向下執行。Golang 中的 WaitGroup 一直是同步 goroutine 的推薦實踐。自己用了兩年多也沒遇到過什麼問題。
直到最近的一天同事扔過來一段奇怪的代碼:
好了,到這裡終於解決了,以上就是關於Go語言WaitGroup使用時需要注意的一些坑,希望本文中提到的這些問題對大家學習或者使用Go語言的時候能有所幫助,如果有疑問大家可以留言交流。
怎樣理解golang的異步
同步的意思是,後一條指令必須要等待上一條指令執行完成後,才開始運行;異步呢就是,上一條指令啟動後,就在“另一個維度”運行了,和下一條指令好像是同時運行的,更為生動的說法,我照搬一下一個百度知道的神比喻:
你給了狗一個包子,然後就走開做別的事去了,過後狗追過來對你說了聲謝謝,
或者咬了你一口說,包子有毒。這是異步。
同樣你給了狗一個包子後,看着狗把包子吃完,並對你搖尾巴,這個期間你一點別的
事都不做,就等着狗吃完包子。 這是同步。
用你問題中的代碼,可以理解為:
你再給了狗一個包子,然後就呆在原地除了等狗啥都不做,過會兒狗追過來對你說了聲謝謝,你再心滿意足地繼續做自己的事情,這就是將異步阻塞後變成的同步。
所以呢,同步和阻塞還是有那麼些聯繫的(如果你把它們揉在一起的話)。
再說回 golang,其實你代碼中,也就兩個 go 語句是達到這個效果了的,但相對於 fmt.Println(“繼續執行”) 以及後面的代碼來說,前兩條語句還是異步執行的,並且它不像 javascript 那樣只是單線程工作(並發),golang 協程是可以多個同時工作的(並行)
go語言無緩衝的channel
無緩衝的通道(unbuffered channel)是指在接收前沒有能力保存任何值的通道。
這種類型的通道要求發送goroutine和接收goroutine同時準備好,才能完成發送和接收操作。否則,通道會導致先執行發送或接收操作的 goroutine 阻塞等待。
這種對通道進行發送和接收的交互行為本身就是同步的。其中任意一個操作都無法離開另一個操作單獨存在。
阻塞:由於某種原因數據沒有到達,當前協程(線程)持續處於等待狀態,直到條件滿足,才接觸阻塞。
同步:在兩個或多個協程(線程)間,保持數據內容一致性的機制。
下圖展示兩個 goroutine 如何利用無緩衝的通道來共享一個值:
在第 1 步,兩個 goroutine 都到達通道,但哪個都沒有開始執行發送或者接收。
在第 2 步,左側的 goroutine 將它的手伸進了通道,這模擬了向通道發送數據的行為。這時,這個 goroutine 會在通道中被鎖住,直到交換完成。
在第 3 步,右側的 goroutine 將它的手放入通道,這模擬了從通道里接收數據。這個 goroutine 一樣也會在通道中被鎖住,直到交換完成。
在第 4 步和第 5 步,進行交換,並最終,在第 6 步,兩個 goroutine 都將它們的手從通道里拿出來,這模擬了被鎖住的 goroutine 得到釋放。兩個 goroutine 現在都可以去做別的事情了。
如果沒有指定緩衝區容量,那麼該通道就是同步的,因此會阻塞到發送者準備好發送和接收者準備好接收。
無緩衝channel: —— 同步通信
golang的線程模型——GMP模型
內核線程(Kernel-Level Thread ,KLT)
輕量級進程(Light Weight Process,LWP):輕量級進程就是我們通常意義上所講的線程,由於每個輕量級進程都由一個內核線程支持,因此只有先支持內核線程,才能有輕量級進程
用戶線程與系統線程一一對應,用戶線程執行如lo操作的系統調用時,來回切換操作開銷相對比較大
多個用戶線程對應一個內核線程,當內核線程對應的一個用戶線程被阻塞掛起時候,其他用戶線程也阻塞不能執行了。
多對多模型是可以充分利用多核CPU提升運行效能的
go線程模型包含三個概念:內核線程(M),goroutine(G),G的上下文環境(P);
GMP模型是goalng特有的。
P與M一般是一一對應的。P(上下文)管理着一組G(goroutine)掛載在M(內核線程)上運行,圖中左邊藍色為正在執行狀態的goroutine,右邊為待執行狀態的goroutiine隊列。P的數量由環境變量GOMAXPROCS的值或程序運行runtime.GOMAXPROCS()進行設置。
當一個os線程在執行M1一個G1發生阻塞時,調度器讓M1拋棄P,等待G1返回,然後另起一個M2接收P來執行剩下的goroutine隊列(G2、G3…),這是golang調度器厲害的地方,可以保證有足夠的線程來運行剩下所有的goroutine。
當G1結束後,M1會重新拿回P來完成,如果拿不到就丟到全局runqueue中,然後自己放到線程池或轉入休眠狀態。空閑的上下文P會周期性的檢查全局runqueue上的goroutine,並且執行它。
另一種情況就是當有些P1太閑而其他P2很忙碌的時候,會從其他上下文P2拿一些G來執行。
詳細可以翻看下方第一個參考鏈接,寫得真好。
最後用大佬的總結來做最後的收尾————
Go語言運行時,通過核心元素G,M,P 和 自己的調度器,實現了自己的並發線程模型。調度器通過對G,M,P的調度實現了兩級線程模型中操作系統內核之外的調度任務。整個調度過程中會在多種時機去觸發最核心的步驟 “一整輪調度”,而一整輪調度中最關鍵的部分在“全力查找可運行G”,它保證了M的高效運行(換句話說就是充分使用了計算機的物理資源),一整輪調度中還會涉及到M的啟用停止。最後別忘了,還有一個與Go程序生命周期相同的系統監測任務來進行一些輔助性的工作。
淺析Golang的線程模型與調度器
Golang CSP並發模型
Golang線程模型
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/206743.html