Ist diese Beispielverwendung sync.WaitGroup
korrekt? Es gibt das erwartete Ergebnis, aber ich bin mir nicht sicher über die wg.Add(4)
und die Position von wg.Done()
. Ist es sinnvoll, die vier Goroutinen gleichzeitig mit hinzuzufügen wg.Add()
?
http://play.golang.org/p/ecvYHiie0P
package main
import (
"fmt"
"sync"
"time"
)
func dosomething(millisecs time.Duration, wg *sync.WaitGroup) {
duration := millisecs * time.Millisecond
time.Sleep(duration)
fmt.Println("Function in background, duration:", duration)
wg.Done()
}
func main() {
var wg sync.WaitGroup
wg.Add(4)
go dosomething(200, &wg)
go dosomething(400, &wg)
go dosomething(150, &wg)
go dosomething(600, &wg)
wg.Wait()
fmt.Println("Done")
}
Ergebnis (wie erwartet):
Function in background, duration: 150ms
Function in background, duration: 200ms
Function in background, duration: 400ms
Function in background, duration: 600ms
Done
defer wg.Done()
Aufruf zu Beginn der Funktion empfehlen .Antworten:
Ja, dieses Beispiel ist korrekt. Es ist wichtig, dass das
wg.Add()
vor dergo
Aussage passiert , um Rennbedingungen zu verhindern. Folgendes wäre auch richtig:Es ist jedoch ziemlich sinnlos, immer wieder anzurufen,
wg.Add
wenn Sie bereits wissen, wie oft es angerufen wird.Waitgroups
Panik, wenn der Zähler unter Null fällt. Der Zähler beginnt bei Null, jederDone()
ist a-1
und jederAdd()
hängt vom Parameter ab. Also, um sicherzustellen , dass der Zähler nie unter Tropfen und vermeiden Sie gerät in Panik, müssen Sie dieAdd()
zu gewährleistet , bevor die kommenDone()
.In Go werden solche Garantien vom Speichermodell gegeben .
Das Speichermodell besagt, dass alle Anweisungen in einer einzelnen Goroutine in derselben Reihenfolge ausgeführt werden, in der sie geschrieben wurden. Es ist möglich, dass sie nicht in dieser Reihenfolge sind, aber das Ergebnis wird so sein, als ob es so wäre. Es ist auch garantiert, dass eine Goroutine erst nach der
go
Anweisung ausgeführt wird, die sie aufruft . Da dasAdd()
vor dergo
Anweisung und diego
Anweisung vor dem auftrittDone()
, wissen wir, dass dasAdd()
vor dem auftrittDone()
.Wenn Sie die
go
Anweisung vor dem habenAdd()
, funktioniert das Programm möglicherweise ordnungsgemäß. Es wäre jedoch eine Rennbedingung, da dies nicht garantiert werden würde.quelle
defer wg.Done()
Wäre es nicht besser, wenn wir sicher sind, dass sie unabhängig von der Route der Goroutine aufgerufen wird? Vielen Dank.defer
und eine Ihrer Goroutinen nicht anruftwg.Done()
...Wait
blockieren Sie nicht einfach für immer? Das klingt so, als könnte es leicht zu einem schwer zu findenden Fehler in Ihrem Code kommen ...Ich würde empfehlen, den
wg.Add()
Aufruf in diedoSomething()
Funktion selbst einzubetten , damit Sie den Parameter add nicht manuell anpassen müssen, wenn Sie die Anzahl der Aufrufe anpassen. Dies kann zu einem Fehler führen, wenn Sie einen aktualisieren, aber vergessen, den zu aktualisieren andere (in diesem trivialen Beispiel ist das unwahrscheinlich, aber ich persönlich glaube, dass es eine bessere Praxis für die Wiederverwendung von Code ist).Wie Stephen Weinberg in seiner Antwort auf diese Frage hervorhebt, müssen Sie die Wartegruppe vor dem Laichen des Gofunc erhöhen. Sie können dies jedoch leicht erreichen, indem Sie den Gofunc-Spawn
doSomething()
wie folgt in die Funktion selbst einwickeln :Dann können Sie es ohne
go
Aufruf aufrufen , zB:Als Spielplatz: http://play.golang.org/p/WZcprjpHa_
quelle
quelle