Heim  >  Artikel  >  Backend-Entwicklung  >  Über Mutex in der gleichzeitigen Go-Programmierung

Über Mutex in der gleichzeitigen Go-Programmierung

藏色散人
藏色散人nach vorne
2020-11-16 13:53:522536Durchsuche
Go

vorzustellen. Ich hoffe, dass es den Freunden, die es brauchen, hilfreich sein wird! Freundliche Erinnerung: Das Lesen dieses Artikels dauert etwa 5 Minuten und 45 Sekunden. Bitte geben Sie mir weitere Hinweise zu etwaigen Mängeln. Beim Entwurf unserer häufigeren Großprojekte treten häufig Parallelitätsprobleme auf, um die Genauigkeit der Daten zu verbessern und sicherzustellen, dass die Daten im selben kritischen Abschnitt nur von einem Thread bearbeitet werden können Szenarien, die im täglichen Leben verwendet werden. Von:

Zähler

: Das Zählerergebnis ist ungenau;

    Sekunden-Kill-System
  • : Überverkauft aufgrund einer großen Anzahl von Besuchen gleichzeitig; Überziehung durch gleichzeitige Zahlung;
  • Pufferdatenausnahme
  • : Datenverwirrung durch Aktualisierung des Puffers.
  • Bei allen oben genannten Problemen handelt es sich um Probleme der Datengenauigkeit, die durch Parallelität verursacht werden. Die entscheidende Lösung ist die Verwendung von
  • Mutex-Sperre, dem Mutex-Parallelitätsprimitiv, das in der heutigen gleichzeitigen Programmierung beschrieben wird.
  • Implementierungsmechanismus
  • Mutex-Sperre Mutex ist ein Parallelitätskontrollmechanismus, der eingerichtet wurde, um Parallelitätskonkurrenz zu vermeiden. Es enthält das Konzept eines „kritischen Abschnitts“.

Wenn im Prozess der gleichzeitigen Programmierung gleichzeitig auf einige Ressourcen oder Variablen im Programm zugegriffen oder diese geändert werden, muss dieser Teil des Programms zuerst geschützt und dann betrieben werden, um Datenungenauigkeiten durch gleichzeitigen Zugriff zu vermeiden. und der Schutz nach Abschluss des Vorgangs entfernt wird, wird dieser Teil des geschützten Programms als „kritischer Abschnitt“ bezeichnet.

Verwenden Sie eine Mutex-Sperre, um den kritischen Abschnitt so zu begrenzen, dass er gleichzeitig nur von einem Thread gehalten wird. Wenn der kritische Abschnitt zu diesem Zeitpunkt von einem Thread gehalten wird, schlagen andere Threads fehl oder warten, bis sie eintreten möchten Wenn Sie die Sperre aufheben, wird der Thread, der diesen kritischen Abschnitt enthält, beendet und andere Threads haben die Möglichkeit, diesen kritischen Abschnitt abzurufen.

Diagramm des kritischen Abschnitts von Go-Mutex Mutex ist das am weitesten verbreitete Synchronisationsprimitiv in der Go-Sprache, auch Parallelitätsprimitiv genannt.

Es löst das Problem des gleichzeitigen Lesens und Schreibens gemeinsam genutzter Ressourcen, um Datenwettlaufprobleme zu vermeiden .

Grundlegende Verwendung

Mutex bietet zwei Methoden: Sperren und Entsperren: Verwenden Sie beim Betreten des kritischen Abschnitts die Lock-Methode zum Sperren und beim Verlassen des kritischen Abschnitts die Unlock-Methode, um die Sperre aufzuheben.

type Locker interface {
    Lock()
    Unlock()}func(m *Mutex)Lock()func(m *Mutex)Unlock()

Wenn eine Goroutine die Lock-Methode aufruft, um die Sperre zu erhalten, blockieren andere Goroutinen den Lock-Aufruf, bis die Goroutine, die gerade die Sperre erwirbt, die Sperre aufhebt.

Das Folgende ist ein Beispiel für einen Zähler, der von 100 Goroutinen ausgeführt wird, um den Zähler zu akkumulieren, und das endgültige Ausgabeergebnis ist:

package mainimport (
    "fmt"
    "sync")func main() {
    var mu sync.Mutex
    countNum := 0

    // 确认辅助变量是否都执行完成
    var wg sync.WaitGroup    // wg 添加数目要和 创建的协程数量保持一致
    wg.Add(100)
    for i := 0; i < 100; i++ {
        go func() {
            defer wg.Done()
            for j := 0; j < 1000; j++ {
                mu.Lock()
                countNum++
                mu.Unlock()
            }
        }()
    }
    wg.Wait()
    fmt.Printf("countNum: %d", countNum)}

Tatsächliche Verwendung

Oft wird Mutex nicht allein verwendet, sondern verschachtelt in einer Struktur Wird als Teil der Struktur verwendet. Wenn die eingebettete Struktur mehrere Felder hat, platzieren wir normalerweise den Mutex auf dem zu steuernden Feld und verwenden dann Leerzeichen, um die Felder zu trennen.

Sie können sogar die Logik des Erwerbs von Sperren, der Freigabe von Sperren und des Zählens um eins in einer Methode kapseln.

package mainimport (
    "fmt"
    "sync")// 线程安全的计数器type Counter struct {
    CounterType int
    Name        string

    mu    sync.Mutex
    count uint64}// 加一方法func (c *Counter) Incr() {
    c.mu.Lock()
    defer c.mu.Unlock()
    c.count++}// 取数值方法 线程也需要受保护func (c *Counter) Count() uint64 {
    c.mu.Lock()
    defer c.mu.Unlock()
    return c.count}func main() {
    // 定义一个计数器
    var counter Counter    var wg sync.WaitGroup
    wg.Add(100)

    for i := 0; i < 100; i++ {
        go func() {
            defer wg.Done()
            for j := 0; j < 1000; j++ {
                counter.Incr()
            }
        }()
    }
    wg.Wait()

    fmt.Printf("%d\n", counter.Count())}

Denkfragen

F: Sie wissen bereits, dass andere wartende Goroutinen nur ewig warten können, wenn ein Mutex von einer Goroutine gesperrt wurde. Welche der wartenden Goroutinen erhält den Mutex also zuerst, nachdem die Sperre aufgehoben wurde?

A: FIFO-Strategie: Bei der Goroutine-Planung wird eine Warteschlange verwaltet, um die Ausführung der Goroutine sicherzustellen. Wenn die Goroutine, die die Sperre erhält, den Vorgang des kritischen Abschnitts abschließt, wird die Sperre freigegeben. In der Warteschlange Die in der Warteschlange an erster Stelle stehende Goroutine erhält die Sperre und führt kritische Abschnittsoperationen aus.                                                                           

Das obige ist der detaillierte Inhalt vonÜber Mutex in der gleichzeitigen Go-Programmierung. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:learnku.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen