亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

wg.Add() 放在哪里

wg.Add() 放在哪里

Go
慕絲7291255 2022-07-18 16:54:15
var wg sync.WaitGroupvar v int32 = 0 for i = 0; i < 100; i++{   go func(){       wg.Add(1) // wrong place       atomic.AddInt32(&v,1)       wg.Done()   } }wg.Wait()fmt.Println(v)這是我從該視頻中看到的一段代碼https://subscription.packtpub.com/video/application_development/9781788994880/97598/97608/goroutines但是v總是小于100,我認為原因可能是wg.Wait()比預期更早結束,因為我們把wg.Add(1)匿名函數放在里面,并且在同一個 goroutinewg.Done()中會立即被調用,因此 main goroutine 從阻塞狀態恢復執行。但是如果我們將wg.Add(1)放入 for 循環中, v 將永遠是100。var wg sync.WaitGroupvar v int32 = 0 for i = 0; i < 100; i++{   wg.Add(1)   go func(){       atomic.AddInt32(&v,1)       wg.Done()   } }wg.Wait()fmt.Println(v)我的問題是為什么我們可以保證 main goroutine 總是會在這里阻塞,使得 v 最終等于 100。如果在 for 循環之前添加一個任務到wg, 并且 main goroutine 在這里恢復執行,那是否可能,因為此時沒有任務。
查看完整描述

2 回答

?
慕田峪7331174

TA貢獻1828條經驗 獲得超13個贊

wg.Add()在啟動將調用的 goroutine 之前,您應該始終調用wg.Done().

在您更正的示例中,maingoroutine 只能wg.Wait()for循環之后到達,這可以保證您調用wg.Add()一百次,因此wg.Wait()會阻塞直到wg.Done()被調用100次數。

wg.Add()調用在新的 goroutine 中時,不能保證任何wg.Add()調用都會在maingoroutine 到達之前執行,wg.Wait()因為它們是并發運行的(在此之前沒有同步)。這種情況下的行為是不確定的(取決于 goroutine 調度程序,它在沒有顯式同步的情況下是不確定的)。

請注意,如果您知道循環100進行迭代,另一種選擇是wg.Add(100)在循環之前調用。我建議不要這樣做,因為當循環包含breakcontinue操作時,這需要小心,這可能會導致啟動的 goroutine 更少,從而最終你的maingoroutine 會卡住。是的,在您的情況下,這可能是微不足道的,但如果此代碼及時發展,它可能會變得不那么明顯,并可能導致未來的錯誤。當場景中涉及啟動 goroutine 時,說它更快是無關緊要的。如果您只wg.Add(1)在啟動 goroutine 之前調用,那么稍后您是否有條件地跳過這部分也沒關系,因為您將在wg.Add()啟動 goroutine 的同時跳過,并且您的代碼將保持正確。

使用時要遵循的簡單“規則” sync.WaitGroup:(引自this answer

  • 在語句之前調用WaitGroup.Add()“原始”goroutine(開始一個新的)go

  • 建議調用WaitGroup.Done()deferred,所以即使 goroutine 發生恐慌它也會被調用

  • 如果你想傳遞WaitGroup給其他函數(而不是使用包級變量),你必須傳遞一個指向它的指針,否則WaitGroup(這是一個結構)將被復制,并且Done()不會觀察到在復制上調用的方法在原版上


查看完整回答
反對 回復 2022-07-18
?
吃雞游戲

TA貢獻1829條經驗 獲得超7個贊

就像其他人提到的那樣wg.add(),應該在調用任何 go 例程之前調用。所以在主線程里面:


一開始就推遲是一種很好的做法,這樣你就不會忘記,因為它被視為清理行動。


var wg sync.WaitGroup

var v int32 = 0 

for i = 0; i < 100; i++{

   wg.Add(1) //right place to put wg.add(1)

   go func(){

       defer wg.Done()

       atomic.AddInt32(&v,1)

   } 

}

wg.Wait()

fmt.Println(v)


查看完整回答
反對 回復 2022-07-18
  • 2 回答
  • 0 關注
  • 556 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號