如果你正在學習go的高效能併發應用開發,那麼了解同步等待組至關重要。本文帶你認識同步等待組並通過示例進行說明。
讓我們直入主題,說明是同步等待組(waitgroup),能夠解決什麼問題。
在實際使用go協程實現並行應用時,可能會遇到這樣場景:需要阻塞部分**執行,直到其他協程成功執行之後才繼續執行。
示例**:
package main
import "fmt"
func myfunc()
func main()
程式首先列印"hello world",接著啟動協程,最後列印"finished execution"。
但我們執行程式結果並不是我們預期的結果,協程內的資訊"inside my goroutine"並沒有出現。這是因為main在協程執行之前以及結束,所以協程中的邏輯並未執行。
如何解決————同步等待組(waitgroups)
同步等待組(waitgroups)就是要解決這類問題,阻塞應用直到同步等待組中的所有協程都成功執行。
首先呼叫同步等待組的add(1)方法,設定需要等待協程數量, 然後再協程內部呼叫done()
方法表明協程執行結束。
注意,需要確保再執行協程之前呼叫add(1)
方法。
掌握了一些基本概念後,下面通過示例展示如何通過同步等待組解決上述問題:
package main
import (
"fmt"
"sync"
)func myfunc(waitgroup *sync.waitgroup)
func main()
我們看到首先例項化sync.waitgroup
,然後再執行協程之前呼叫add(1)
方法。修改原來函式增加*sync.waitgroup
引數,並在函式內部成功完成任務後呼叫一次done
方法。最後呼叫waitgroup.wait()
方法阻塞main函式執行,直到同步等待組中的協程成功執行完成。
下面再次執行程式輸出結果如下:
hello world
inside my goroutine
finished execution
我們也可以使用匿名函式實現相同功能。對於協程內部業務不複雜,匿名函式會讓程式更簡潔:
package main
import (
"fmt"
"sync"
)func main() ()
waitgroup.wait()
fmt.println("finished execution")
}
輸出結果一樣。對於稍微複雜的邏輯,可能需要給匿名函式傳入引數,例如需要傳入url引數:
go func(url string) (url)
只是寫法有點差異,其他都差不多。
在示例生產應用程式中,任務是建立乙個api,該api與大量其他api互動,並將結果聚合到乙個響應中。每個api呼叫大約花費2-3秒時間來返回響應,由於需要呼叫的api數量太多,不可能同步地進行此操作。
為了實現該功能,需要使用協程非同步執行這些請求。
func main()然而當我開始使用這種策略時,我注意到我對任何api呼叫都在協程有機會完成填充結果之前返回。這時需要使用同步等待組重新實現該功能,通過使用waitgroup,我可以有效地修復這種異常行為,並且只在所有goroutines完成後返回結果。
func main()現在我們增加同步等待鎖,它將對所有url執行http get請求,一旦執行完畢返回給呼叫客戶端。輸出結果為:
homepage endpoint hit
200 ok
200 ok
200 ok
returning response
處理這類問題的方法不止一種,通過使用golang的通道也可以實現類似功能。本文學習了什麼是golang同步等待組以及如何使用它實現高效能應用。
等待程序結束wait
include include pid t wait int status status 子程序結束時返回的終止狀態 子程序是怎麼結束的 status是乙個傳出引數 如果父程序不關心子程序的狀態,向wait中傳入null 功能 等待子程序結束 阻塞等待 成功 返回子程序的pid,失敗 返回 1擴充套...
程序的等待 wait函式
wait函式 include include pid t wait int status 功能 等待子程序終止,如果子程序終止了,此函式會 子程序的資源。呼叫wait函式的程序會掛起,直到它的乙個子程序退出或收到乙個不能被忽視的訊號時才被喚醒。若呼叫程序沒有子程序或它的子程序已經結束,該函式立即返回...
程序的等待(wait和waitpid)
1.程序的等待 wait函式或waitpid程序可能發生如下情況 1 如果所有的子程序孩子執行,則阻塞 block 2 如果乙個子程序已經終止,正等待父程序獲取其終止狀態,則取得孩子程序的終止狀態返回 3 如果她沒有任何子程序,則立即出錯返回 函式的原型 include pid t wait int...