Dans le langage Go, goroutine peut être utilisé pour exécuter des tâches simultanément, et sync.WaitGroup est un mécanisme de synchronisation utilisé pour attendre la fin d'un groupe de goroutines. Cependant, l'éditeur PHP Banana a constaté que dans certains cas, l'utilisation de goroutine avec sync.WaitGroup peut conduire à des résultats incohérents. Ce problème se produit généralement lorsque plusieurs goroutines modifient des variables partagées en même temps. L'ordre d'exécution des goroutines étant incertain, cela peut entraîner une incohérence dans les résultats finaux. Dans cet article, nous explorerons les causes de ce problème et proposerons quelques solutions pour garantir la cohérence des résultats entre les goroutines.
J'essaie d'utiliser goroutine (en langage Go) pour compter le nombre de nombres premiers inférieurs à n'importe quel nombre entier i
.
Par exemple, si i
为 100,则结果应为 25
vaut 100, le résultat devrait être 25
.
Voici ma mise en œuvre actuelle :
<code>package "main" import ( "fmt" "math" "sync" "time" ) var wg sync.WaitGroup func isprime(x int) bool { if x == 2 { return true } if x == 1 || x%2 == 0 { return false } var xi = float64(x) for i := 3; float64(i) < (math.Pow(xi, 0.5) + 1.0); i += 2.0 { if x%i == 0 { return false } } return true } func main() { fmt.Print("Till what number should I count primes? ") var i int fmt.Scan(&i) r := 0 pr := &r fmt.Println("Counting primes till ", i) start := time.Now() for x := 0; x <= i; x++ { wg.Add(1) go func(n int) { defer wg.Done() if isprime(n) { *pr += 1 } }(x) } wg.Wait() elapsed := time.Since(start).Seconds() fmt.Println("Counted", r, "primes") fmt.Println("took", elapsed, "seconds") } </code>
Lorsque j'exécute ce programme, j'obtiens des résultats corrects pour des valeurs i
plus petites (jusqu'à environ 1000)
Mais pour les valeurs i
plus grandes, les résultats sont incohérents et incorrects.
❯ ./main Till what number should I count primes? 10000 Counting primes till 10000 Counted 1228 primes took 0.006776541 seconds ❯ ./main Till what number should I count primes? 10000 Counting primes till 10000 Counted 1227 primes took 0.004183875 seconds ❯ ./main Till what number should I count primes? 1000000 Counting primes till 1000000 Counted 78254 primes took 0.441985921 seconds ❯ ./main Till what number should I count primes? 1000000 Counting primes till 1000000 Counted 78327 primes took 0.430042047 seconds
À mesure que la valeur de i
的值变大,结果波动增大。是什么原因造成的?有什么方法可以使其一致且正确吗?
您有一个共享变量,但没有适当的同步。存在竞争条件(*pr += 1
)。在共享变量前后添加互斥体修复它(mu.Lock()、mu.Unlock()
augmente, la fluctuation du résultat augmente. Quelle est la cause de cela ? Existe-t-il un moyen de le rendre cohérent et correct ?
Solution
Vous avez une variable partagée mais pas de synchronisation appropriée. Une condition de concurrence critique existe (*pr += 1
). L'ajout de mutex avant et après la variable partagée la corrige (mu.Lock(), mu.Unlock()
).
var wg sync.WaitGroup var mu sync.Mutex func main() { fmt.Print("Till what number should I count primes? ") var i int fmt.Scan(&i) r := 0 pr := &r fmt.Println("Counting primes till ", i) start := time.Now() for x := 0; x <= i; x++ { wg.Add(1) go func(n int) { defer wg.Done() if isprime(n) { mu.Lock() // <= lock *pr += 1 mu.Unlock() // <= unlock } }(x) } wg.Wait() elapsed := time.Since(start).Seconds() fmt.Println("Counted", r, "primes") fmt.Println("took", elapsed, "seconds") }
Till what number should I count primes? 1000000 Counting primes till 1000000 Counted 78498 primes took 0.6783484 seconds Till what number should I count primes? 1000000 Counting primes till 1000000 Counted 78498 primes took 0.5428273 seconds Till what number should I count primes? 1000000 Counting primes till 1000000 Counted 78498 primes took 0.5521617 seconds
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!