Heim  >  Artikel  >  Backend-Entwicklung  >  Studieren Sie Golangs Lock-Implementierung

Studieren Sie Golangs Lock-Implementierung

PHPz
PHPzOriginal
2023-12-28 10:32:43665Durchsuche

Studieren Sie Golangs Lock-Implementierung

Erkundung des Implementierungsmechanismus von Golang-Sperren

Einführung:

Bei der gleichzeitigen Programmierung ist Sperre (Lock) ein häufig verwendeter Synchronisationsmechanismus, der zum Schutz des Zugriffs auf gemeinsam genutzte Ressourcen verwendet wird. Als Programmiersprache mit hoher Parallelitätsleistung und prägnanter Syntax bietet Golang eine Fülle von Sperrmechanismen, darunter Mutex (Mutex), Lese-/Schreibsperre (RWMutex) usw. In diesem Artikel wird der Implementierungsmechanismus von Golang-Sperren untersucht und anhand spezifischer Codebeispiele demonstriert.

1. Implementierungsmechanismus der Mutex-Sperre (Mutex)

  1. Implementierung der Sperrmethode:

Der Implementierungsmechanismus der Mutex-Sperre besteht hauptsächlich aus drei wichtigen Komponenten: Warteschlange, Statusflag und atomare Operation. Wenn ein Thread versucht, eine Mutex-Sperre zu erhalten, prüft er zunächst das Statusflag. Wenn das Statusflag gesperrt ist, fügt er sich selbst der Warteschlange hinzu und dreht sich, um zu warten. Wenn das Statusflag entsperrt ist, versuchen Sie, die Sperre mit atomaren Operationen zu erhalten und das Statusflag auf gesperrt zu setzen. Das Folgende ist ein spezifisches Codebeispiel einer Mutex-Sperre:

type Mutex struct {
    waiting   int32 // 等待队列,记录等待获取锁的goroutine数量
    isLocked  int32 // 锁的状态标志,0代表未锁住,1代表已锁住
}

func (m *Mutex) Lock() {
    for !atomic.CompareAndSwapInt32(&m.isLocked, 0, 1) { // 自旋等待获取锁
        runtime.Gosched()
    }
}

func (m *Mutex) Unlock() {
    atomic.StoreInt32(&m.isLocked, 0) // 释放锁,将状态标志设置为未锁住
}
  1. Implementierung einer atomaren Operation:

Der obige Code verwendet die Funktionen CompareAndSwapInt32 und StoreInt32 im Atompaket, um atomare Operationen zu implementieren. Die Funktion CompareAndSwapInt32 wird für Vergleichs- und Austauschvorgänge verwendet. Wenn das Statusflag der Sperre entsperrt ist, wird sie auf „gesperrt“ gesetzt und gibt „true“ zurück, wenn das Statusflag der Sperre gesperrt ist. Die StoreInt32-Funktion wird verwendet, um das Statusflag atomar auf entsperrt zu setzen. Diese atomaren Operationen können das Auftreten von Race Conditions wirksam verhindern und die Richtigkeit der Sperre sicherstellen.

2. Implementierungsmechanismus der Lese-/Schreibsperre (RWMutex)

  1. Implementierungsmechanismus der Schreibsperre:

Die Lese-/Schreibsperre ist ein spezieller Sperrmechanismus, der es mehreren Goroutinen ermöglicht, gemeinsam genutzte Ressourcen gleichzeitig zu lesen, jedoch nur Eine Goroutine schreibt in eine gemeinsam genutzte Ressource. Der Implementierungsmechanismus der Schreibsperre ähnelt dem der Mutex-Sperre, es gibt jedoch einige Unterschiede. Das Folgende ist ein spezifisches Codebeispiel einer Schreibsperre:

type RWMutex struct {
    writerSem uint32    // 写入信号量,用于限制只能有一个goroutine写入
    readerSem uint32    // 读取信号量,用于限制多个goroutine同时读取
    readerCount int32   // 读取计数,记录当前同时读取的goroutine数量
    readerWait  int32   // 当前等待读取的goroutine数量
}

func (rw *RWMutex) Lock() {
    rw.lockWhile(func() {atomic.LoadUint32(&rw.readerSem) != 0 || atomic.LoadUint32(&rw.writerSem) != 0})
    atomic.AddUint32(&rw.writerSem, 1) // 获取写锁,递增写入信号量
}

func (rw *RWMutex) Unlock() {
    atomic.AddUint32(&rw.writerSem, ^uint32(0)) // 释放写锁,递减写入信号量
    rw.unlockWhile(func() {atomic.LoadInt32(&rw.readerCount) != 0}) // 释放读锁,根据读取计数判断是否需要唤醒等待读取的goroutine
}
  1. Implementierungsmechanismus der Lesesperre:

Der Implementierungsmechanismus der Lesesperre wird hauptsächlich durch Erhöhen des Lesesemaphors und der Leseanzahl implementiert, wenn eine Goroutine die Lesesperre erhält , prüft es zunächst, ob das Schreibsemaphor Null ist und keine anderen Goroutinen auf das Schreiben warten. Wenn ja, erhöhen Sie die Leseanzahl und erwerben Sie die Lesesperre, andernfalls fügen Sie sich selbst zur Warteschlange für das Spin-Warten hinzu. Das Folgende ist ein spezifisches Codebeispiel einer Lesesperre:

func (rw *RWMutex) RLock() {
    rw.lockWhile(func() {atomic.LoadUint32(&rw.writerSem) != 0}) // 当有 goroutine 持有写锁时,自旋等待
    atomic.AddInt32(&rw.readerCount, 1) // 递增读取计数
}

func (rw *RWMutex) RUnlock() {
    atomic.AddInt32(&rw.readerCount, -1) // 递减读取计数
    rw.unlockWhile(func() {atomic.LoadInt32(&rw.readerCount) != 0}) // 根据读取计数判断是否需要唤醒等待读取的goroutine
}
  1. Wecken Sie die wartende Goroutine auf:

In der Implementierung der Lese-/Schreibsperre gibt es eine Operation zum Aufwecken der wartenden Goroutine. Es wird durch zwei Hilfsfunktionen implementiert: lockWhile und unlockWhile. Die lockWhile-Funktion wird für das Spin-Waiting verwendet. Wenn die gegebene Bedingung wahr ist, wird die Goroutine blockiert, bis die Bedingung erfüllt ist sperren. Dies stellt sicher, dass Goroutinen, die auf Sperren warten, rechtzeitig aktiviert werden können, und verbessert die Parallelitätsleistung.

Zusammenfassung:

In diesem Artikel haben wir den Implementierungsmechanismus von Sperren in Golang eingehend untersucht und anhand spezifischer Codebeispiele demonstriert. Mutex-Sperren werden durch Warteschlangen und Statusflags implementiert, um sicherzustellen, dass nur eine Goroutine die Sperre halten kann, während Lese-/Schreibsperren durch Schreibsemaphoren, Lesesemaphoren und Lesezählungen implementiert werden, sodass mehrere Goroutinen gleichzeitig lesen und schreiben können. Nur eine Goroutine darf schreiben. Diese Sperrmechanismen gewährleisten einen sicheren Zugriff auf gemeinsam genutzte Ressourcen und verbessern die Leistung gleichzeitiger Programme durch atomare Operationen und bedingtes Warten.

Das obige ist der detaillierte Inhalt vonStudieren Sie Golangs Lock-Implementierung. 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