Heim  >  Artikel  >  Backend-Entwicklung  >  Ist Golang-Parallelität unsicher?

Ist Golang-Parallelität unsicher?

PHPz
PHPzOriginal
2023-03-30 09:04:37825Durchsuche

Golang hat als relativ junge Programmiersprache in den letzten Jahren durch seine rasante Entwicklung immer mehr Aufmerksamkeit und Liebe auf sich gezogen. Der integrierte Parallelitätsmechanismus von Golang wird von vielen Entwicklern bevorzugt, aber die Verwendung des Parallelitätsmechanismus birgt einige versteckte Gefahren, insbesondere wenn die Parallelität unsicher ist, kann dies zu einer Reihe von Problemen im Programm führen. In diesem Artikel werden die Gründe und Lösungen für unsichere Parallelität in Golang untersucht.

1. Gründe, warum Parallelität unsicher ist

Eine Rennbedingung bedeutet, dass die Ergebnisse verwirrend sind, wenn mehrere Threads aufgrund unterschiedlicher Vorgänge auf gemeinsame Ressourcen zugreifen. In Golang sind die Rennbedingungen aufgrund der asynchronen Ausführung von Coroutinen offensichtlicher.

2. Datenwettbewerb

Datenwettbewerb bedeutet, dass mehrere Coroutinen gleichzeitig auf denselben Speicherbereich zugreifen und mindestens eine Coroutine einen Schreibvorgang ausführt. Aufgrund des Parallelitätsmechanismus von Golang haben verschiedene Coroutinen unterschiedliche Ausführungszeiten, sodass mehrere Coroutinen möglicherweise gleichzeitig denselben Speicherbereich ändern.

3. Deadlock

Deadlock bezieht sich auf eine Situation, in der zwei oder mehr Coroutinen aufeinander warten, um Ressourcen freizugeben, und die Ausführung nicht fortsetzen können. Diese Situation kann bei Verwendung einer Sperre auftreten. Bei unsachgemäßer Verwendung der Sperre kommt es zu einem Deadlock.

2. Beispiel für unsichere Parallelität in Golang

Das Folgende ist ein einfaches Beispiel, um das Problem der unsicheren Parallelität in Golang zu erklären:

package main 
import (
   "fmt"
   "sync"
)
var num = 0 
func add(wg *sync.WaitGroup) {
   num++ 
   wg.Done()
}
func main() {
   var wg sync.WaitGroup
   for i := 0; i < 1000; i++ {
      wg.Add(1)
      go add(&wg)
   }
   wg.Wait()
   fmt.Println("num=", num)
}

In diesem Beispiel definieren wir eine globale Variable num und verwenden eine Coroutine, um die add-Methode aufzurufen. Erhöhe die Zahl um das 1000-fache. Aufgrund der asynchronen Ausführung von Coroutinen ist die Ausführungsreihenfolge dieses Programms ungewiss. Wenn dieser Code mehrere Coroutinen gleichzeitig ausführt, kommt es zu Datenkonkurrenz und das Ergebnis von num ist möglicherweise nicht die 1000, die wir erwarten.

3. So vermeiden Sie unsichere Parallelität

1. Sperren sind eine der am häufigsten verwendeten Methoden zur Lösung unsicherer Parallelitätsprobleme, wie z. B. sync.Mutex und sync.RWMutex , usw. . Durch die Verwendung von Sperren kann sichergestellt werden, dass nur eine Coroutine gleichzeitig auf eine bestimmte Ressource zugreifen kann, wodurch das Auftreten von Datenkonkurrenz vermieden wird.

Ändern Sie das obige Beispiel und verwenden Sie sync.Mutex, um Datenwettläufe zu vermeiden:

package main 
import (
   "fmt"
   "sync"
)
var num = 0 
func add(wg *sync.WaitGroup, lock *sync.Mutex) {
   lock.Lock() 
   num++ 
   lock.Unlock()
   wg.Done()
}
func main() {
   var wg sync.WaitGroup
   var lock sync.Mutex 
   for i := 0; i < 1000; i++ {
      wg.Add(1)
      go add(&wg, &lock)
   }
   wg.Wait()
   fmt.Println("num=", num)
}

In diesem Beispiel verwenden wir sync.Mutex, um sicherzustellen, dass Änderungen an num atomar sind. Dadurch wird das Auftreten von Datenwettläufen vermieden.

2. Verwenden Sie atomare Operationen

Golang bietet eine Reihe von atomaren Operationen, um sicherzustellen, dass die Operation einer bestimmten Ressource atomar ist. Verwenden Sie atomare Operationen, um Race-Bedingungen wie AddInt32, AddInt64, SwapInt32, SwapInt64 usw. im sync/atomic-Paket zu vermeiden.

Ändern Sie das obige Beispiel und verwenden Sie atomare Operationen, um Datenrennen zu vermeiden:

package main 
import (
   "fmt"
   "sync/atomic"
   "sync"
)
var num int32 
func add(wg *sync.WaitGroup) {
   atomic.AddInt32(&num,1) 
   wg.Done()
}
func main() {
   var wg sync.WaitGroup
   for i := 0; i < 1000; i++ {
      wg.Add(1)
      go add(&wg)
   }
   wg.Wait()
   fmt.Println("num=", num)
}

In diesem Beispiel verwenden wir die AddInt32-Funktion im sync/atomic-Paket, um sicherzustellen, dass die Änderung an num atomar ist und Race-Bedingungen vermieden werden.

3. Kanäle verwenden

Kanäle sind ein sehr häufig verwendeter Synchronisationsmechanismus in der gleichzeitigen Golang-Programmierung. Kanäle können sicherstellen, dass die Kommunikation zwischen Coroutinen synchron ist, wodurch Race Conditions und Datenkonkurrenzprobleme vermieden werden.

Ändern Sie das obige Beispiel und verwenden Sie Kanäle, um Datenrennen zu vermeiden:

package main 
import (
   "fmt"
   "sync"
)
func add(wg *sync.WaitGroup, ch chan int) {
   ch <- 1 
   wg.Done()
}
func main() {
   var wg sync.WaitGroup
   ch := make(chan int, 1000)
   for i := 0; i < 1000; i++ {
      wg.Add(1)
      go add(&wg, ch)
   }
   wg.Wait()
   close(ch)
   num := 0 
   for n := range ch {
      num += n
   }
   fmt.Println("num=", num)
}

In diesem Beispiel verwenden wir Kanäle, um sicherzustellen, dass Änderungen an num synchronisiert werden, wodurch das Auftreten von Datenrennen vermieden wird.

4. Zusammenfassung

Golangs Parallelitätsmechanismus ist eine seiner sehr attraktiven Funktionen, aber die Verwendung des Parallelitätsmechanismus bringt auch gewisse Sicherheitsprobleme mit sich. In diesem Artikel werden die Gründe und Lösungen für die unsichere Parallelität von Golang erörtert und Lösungen hauptsächlich unter den Aspekten der Vermeidung von Datenkonkurrenz, Rennbedingungen und Deadlocks bei der Parallelität bereitgestellt. Im eigentlichen Programmierprozess können wir den geeigneten Mechanismus entsprechend den spezifischen Anforderungen auswählen, um die Qualität und Sicherheit des Programms sicherzustellen.

Das obige ist der detaillierte Inhalt vonIst Golang-Parallelität unsicher?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn