Heim  >  Artikel  >  Backend-Entwicklung  >  So implementieren Sie eine Sperre mit Golang

So implementieren Sie eine Sperre mit Golang

PHPz
PHPzOriginal
2023-04-25 16:28:392677Durchsuche

Golang ist eine sehr beliebte Programmiersprache, die gleichzeitige Programmierung unterstützt. Um die Anforderungen der Parallelitätssicherheit zu erfüllen, bietet Golang einen Sperrmechanismus. Eine Sperre ist ein Synchronisierungsmechanismus, mit dem der Zugriff auf gemeinsam genutzte Ressourcen gesteuert werden kann. In diesem Artikel stellen wir vor, wie man Sperren mit Golang implementiert.

1. Arten von Sperren

In Golang gibt es drei Haupttypen von Sperren: Mutex-Sperren, Lese-/Schreibsperren und Bedingungsvariablen.

1. Mutex-Sperre (Mutex)

Mutex-Sperre ist die einfachste und am häufigsten verwendete Art von Sperre. Seine Funktion besteht darin, nur einem Thread gleichzeitig den Zugriff auf gemeinsam genutzte Ressourcen zu ermöglichen. Wenn andere Threads versuchen, auf die Ressource zuzugreifen, werden sie blockiert, bis die Sperre aufgehoben wird.

2. Lese-Schreib-Sperre (RWMutex)

Lese-Schreib-Sperre ist eine andere Art von Sperre, die es mehreren Threads ermöglicht, gemeinsam genutzte Ressourcen gleichzeitig zu lesen, jedoch nur einen Thread darf diese Ressource schreiben. Diese Sperre ist effizienter als ein Mutex, da sie gleichzeitige Lesevorgänge ermöglicht, Schreibvorgänge jedoch ausschließlich die Ressource belegen müssen.

3. Bedingungsvariable (Cond)

Bedingungsvariable ist ein erweiterter Synchronisationsmechanismus, der einen Mechanismus zum Warten und zur Kommunikation zwischen mehreren Threads bereitstellt. Bedingungsvariablen verfügen über zwei Hauptmethoden: Wait und Signal. Die Wait-Methode kann den Thread in den Ruhezustand versetzen, um auf bestimmte Bedingungen zu warten, während die Signal-Methode den wartenden Thread darüber benachrichtigt, dass die Bedingung erfüllt ist.

2. Implementierung von Mutex-Sperren

Die Standardbibliothek von Golang bietet die Implementierung von Mutex-Sperren. Sie können den Mutex-Typ im Synchronisierungspaket verwenden, um Mutex-Sperren zu implementieren. Das Folgende ist ein Beispielprogramm:

package main

import (
    "fmt"
    "sync"
)

var (
    count int
    lock  sync.Mutex
)

func main() {
    var wg sync.WaitGroup
    for i := 0; i < 100; i++ {
        wg.Add(1)
        go func() {
            lock.Lock()
            count++
            lock.Unlock()
            wg.Done()
        }()
    }
    wg.Wait()
    fmt.Println(count)
}

Im obigen Code definieren wir einen Zählerzähler und erstellen eine Mutex-Sperre. Dann werden 100 Goroutinen gestartet und der Zähler wird in jeder Goroutine um 1 erhöht. Da der Zugriff auf count gleichzeitig erfolgt, müssen wir eine Mutex-Sperre verwenden, um das Auftreten von Race Conditions zu verhindern.

Es ist zu beachten, dass bei Vorgängen mit gemeinsam genutzten Ressourcen der Vorgang nach dem Erwerb der Sperre ausgeführt werden muss und die Sperre nach Abschluss des Vorgangs aufgehoben werden muss, um sicherzustellen, dass alle Vorgänge atomar sind.

3. Implementierung von Lese-/Schreibsperren

Ähnlich wie Mutex-Sperren bietet die Standardbibliothek von Golang auch die Implementierung von Lese-/Schreibsperren. Sie können RWMutex im Synchronisierungspaket verwenden um eine Lese-/Schreibsperre zu implementieren. Das Folgende ist ein Beispielprogramm:

package main

import (
    "fmt"
    "sync"
)

var (
    count int
    rw    sync.RWMutex
)

func main() {
    var wg sync.WaitGroup
    for i := 0; i < 100; i++ {
        wg.Add(1)
        go func() {
            rw.Lock()
            count++
            rw.Unlock()
            wg.Done()
        }()
    }
    for i := 0; i < 100; i++ {
        wg.Add(1)
        go func() {
            rw.RLock()
            fmt.Println(count)
            rw.RUnlock()
            wg.Done()
        }()
    }
    wg.Wait()
}

Im obigen Code verwenden wir den Typ RWMutex, um Lese-/Schreibsperren zu implementieren. Starten Sie zunächst 100 Goroutinen, um 1 zum Zähler hinzuzufügen. Während dieser Zeit kann der Zähler nur von einem Thread belegt werden. Starten Sie dann 100 Goroutinen, um den Zählerwert zu lesen. Diese Goroutinen können den Zählerwert gleichzeitig lesen.

Im Vergleich zu Mutex-Sperren weisen Lese-/Schreibsperren eine höhere Parallelität und weniger Sperrkonflikte auf. Wenn es sich bei den meisten Vorgängen um Lesevorgänge handelt, kann die Verwendung von Lese-/Schreibsperren anstelle von Mutex-Sperren die Leistung verbessern.

4. Implementierung von Bedingungsvariablen

Bedingungsvariablen sind ein erweiterter Synchronisierungsmechanismus, der Threads in den Ruhezustand versetzen und auf die Erfüllung bestimmter Bedingungen warten kann. Bedingungsvariablen werden ebenfalls im Sync-Paket bereitgestellt und können mithilfe des Cond-Typs implementiert werden. Das Folgende ist ein Beispielprogramm:

package main

import (
    "fmt"
    "sync"
)

var (
    count   int
    waiters int
    lock    sync.Mutex
    cond    *sync.Cond = sync.NewCond(&lock)
)

func main() {
    var wg sync.WaitGroup
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func() {
            lock.Lock()
            for count < 5 {
                waiters++
                cond.Wait()
                waiters--
            }
            fmt.Println("Count:", count)
            lock.Unlock()
            wg.Done()
        }()
    }
    for i := 0; i < 5; i++ {
        wg.Add(1)
        go func() {
            lock.Lock()
            count++
            if waiters > 0 {
                cond.Signal()
            }
            lock.Unlock()
            wg.Done()
        }()
    }
    wg.Wait()
}

Im obigen Code definieren wir einen Zählerzähler und einen Count Waiter für wartende Threads. Starten Sie dann 10 Goroutinen, um darauf zu warten, dass der Zähler 5 erreicht, und geben Sie den Wert des Zählers aus, wenn der Zähler 5 erreicht. Starten Sie 5 weitere Goroutinen, um 1 zum Zähler hinzuzufügen. Wenn der Zähler 5 erreicht, rufen Sie cond.Signal() auf, um die wartende Goroutine aufzuwecken.

Es ist zu beachten, dass vor Verwendung der Bedingungsvariablen die Mutex-Sperre erhalten werden muss, da sonst ein Deadlock auftritt.

5. Zusammenfassung

In diesem Artikel werden drei gängige Sperrtypen in Golang vorgestellt: Mutex-Sperren, Lese-/Schreibsperren und Bedingungsvariablen. Mutex-Sperren sind die am häufigsten verwendeten Sperren, um zu verhindern, dass mehrere Threads gleichzeitig auf gemeinsam genutzte Ressourcen zugreifen. Lese-Schreibsperren erlauben mehrere Lesevorgänge, aber nur exklusive Schreibvorgänge. Bedingungsvariablen sind ein erweiterter Synchronisierungsmechanismus, der es Threads ermöglicht, auf die Erfüllung bestimmter Bedingungen zu warten.

Beim Schreiben von Golang-Programmen ist die Wahl des geeigneten Sperrtyps entscheidend, um die Sicherheit der Parallelität zu erreichen. Um die Parallelitätsleistung zu verbessern, muss der entsprechende Sperrtyp entsprechend dem Anwendungsszenario und den spezifischen Anforderungen ausgewählt werden.

Das obige ist der detaillierte Inhalt vonSo implementieren Sie eine Sperre mit Golang. 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