Heim  >  Artikel  >  Backend-Entwicklung  >  Implementierung der Golang-Sperre

Implementierung der Golang-Sperre

WBOY
WBOYOriginal
2023-05-13 09:40:36883Durchsuche

Golang-Sprache ist eine Sprache, die gleichzeitige Programmierung unterstützt, wodurch sie sich sehr gut für die Handhabung von Szenarien mit hoher Parallelität eignet. In Golang sind Sperren eines der wichtigen Werkzeuge, um die Sicherheit der Datenparallelität zu gewährleisten. Sperren können gemeinsam genutzte Daten schützen und Datenverwechslungen durch gleichzeitigen Zugriff verhindern. In diesem Artikel wird die Implementierung von Golang-Sperren vorgestellt, einschließlich Mutex-Sperren, Lese-/Schreibsperren und Bedingungsvariablen.

1. Mutex-Sperre

Mutex-Sperre ist die einfachste Möglichkeit, Sperren in Golang zu implementieren. Das Synchronisierungspaket wird in Golang bereitgestellt und der Typ sync.Mutex ist eine Mutex-Sperre. Mutex-Sperren bieten zwei Methoden: Lock() und Unlock(). Die Lock()-Methode wird verwendet, um die Sperre zu erhalten. Wenn die Sperre von einer anderen Goroutine erworben wurde, wird die Lock()-Methode verwendet, um die Sperre aufzuheben nicht erfasst wurde, führt der Aufruf der Unlock()-Methode zu einer Laufzeitpanik. Ein Beispiel lautet wie folgt:

import "sync"

var lock sync.Mutex

func add(a, b int) int {
    lock.Lock()
    defer lock.Unlock() // 用defer关键字,确保即使函数意外返回也能正确释放锁
    return a + b
}

2. Lese-/Schreibsperre

Der Nachteil einer Mutex-Sperre besteht darin, dass sie exklusiv ist, das heißt, nur eine Goroutine kann die Sperre gleichzeitig erwerben und andere Goroutinen müssen warten. Dies ist in Szenarien mit vielen Lesevorgängen und wenigen Schreibvorgängen sehr verschwenderisch, da die Lesevorgänge die gemeinsam genutzten Daten nicht ändern und gleichzeitig ausgeführt werden können sollten. Um dieses Problem zu lösen, bietet Golang Lese-/Schreibsperren an. Lese-/Schreibsperren haben zwei Zustände: Lesezustand und Schreibzustand. Im Lesezustand können mehrere Goroutinen gleichzeitig Lese-/Schreibsperren erwerben, und im Schreibzustand kann nur eine Goroutine Lese-/Schreibsperren erwerben. Lese-/Schreibsperren bieten drei Methoden: RLock(), RUnlock() und Lock(). Die RLock()-Methode wird verwendet, um die Lesesperre zu erhalten. Wenn zu diesem Zeitpunkt eine oder mehrere Goroutinen die Lesesperre erworben haben, kann die neue Goroutine die Lesesperre direkt erwerben, andernfalls blockiert sie und wartet auf die Freigabe der Lesesperre ; Die RUnlock()-Methode wird verwendet. Die Lock()-Methode wird verwendet, um die Schreibsperre zu erhalten. Wenn eine Goroutine zu diesem Zeitpunkt die Lesesperre oder die Schreibsperre erworben hat, blockiert die neue Goroutine das Warten auf die Sperre freigegeben werden; die Methode Unlock() wird verwendet, um die Schreibsperre aufzuheben. Ein Beispiel ist wie folgt:

import "sync"

var rwLock sync.RWMutex

// 读操作获取读锁,写操作获取写锁
func get(name string) string {
    rwLock.RLock()
    defer rwLock.RUnlock()
    return m[name]
}

func set(name, value string) {
    rwLock.Lock()
    defer rwLock.Unlock()
    m[name] = value
}

3. Bedingungsvariable

Bedingungsvariable ist ein erweitertes Synchronisierungsprimitiv, das einen Mechanismus bereitstellt, der es der Goroutine ermöglicht, auf das Eintreten eines Ereignisses zu warten oder es zu benachrichtigen. Bedingungsvariablen in Golang können über den Cond-Typ im Sync-Paket implementiert werden. Der Cond-Typ bietet drei Methoden: Wait(), Signal() und Broadcast(). Die Wait()-Methode wird verwendet, um auf eine Benachrichtigung in der Warteschlange der Bedingungsvariablen zu warten. Wenn die Benachrichtigung empfangen wird, erhält die Wait()-Methode die Sperre automatisch erneut. Die Signal()-Methode wird verwendet, um eine Benachrichtigung an a zu senden Die zu benachrichtigende Goroutine in der Warteschlange wird von der Wait()-Methode verwendet. Die Broadcast()-Methode wird verwendet, um Benachrichtigungen an alle Goroutinen in der Warteschlange zu senden, und die benachrichtigte Goroutine kehrt von der Wait()-Methode zurück . Ein Beispiel lautet wie folgt:

import "sync"

var cond sync.Cond

// 生产者发送数据
func produce() {
    data := generateData()
    lock.Lock()
    buffer = append(buffer, data)
    lock.Unlock()

    // 发送通知
    cond.Signal()
}

// 消费者获取数据
func consume() {
    lock.Lock()
    // 如果缓冲区为空,则等待通知
    for len(buffer) == 0 {
        cond.Wait()
    }
    data := buffer[0]
    buffer = buffer[1:]
    lock.Unlock()

    processData(data)
}

Zusammenfassung

Durch die detaillierte Einführung der Golang-Sperrenimplementierung können wir verstehen, dass die in Golang bereitgestellten Sperren in drei Typen unterteilt sind: Mutex-Sperren, Lese-/Schreibsperren und Bedingungsvariablen. Mutex-Sperren eignen sich für den exklusiven Zugriff auf gemeinsam genutzte Daten, Lese-/Schreibsperren eignen sich zum Lesen von mehr und Schreiben von weniger und Bedingungsvariablen eignen sich für Warte- und Benachrichtigungsszenarien. In der tatsächlichen Entwicklung sollten wir je nach Szenario geeignete Sperren auswählen, um die Korrektheit und Leistung gleichzeitiger Vorgänge sicherzustellen.

Das obige ist der detaillierte Inhalt vonImplementierung der Golang-Sperre. 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