Maison >développement back-end >Golang >Implémentation du verrouillage Golang

Implémentation du verrouillage Golang

WBOY
WBOYoriginal
2023-05-13 09:40:36933parcourir

Le langage Golang est un langage qui prend en charge la programmation simultanée, ce qui le rend très approprié pour gérer des scénarios à forte concurrence. Dans Golang, les verrous sont l'un des outils importants pour garantir la sécurité de la simultanéité des données. Les verrous peuvent protéger les données partagées et éviter la confusion des données causée par un accès simultané. Cet article présentera l'implémentation des verrous Golang, y compris les verrous mutex, les verrous en lecture-écriture et les variables de condition.

1. Verrouillage Mutex

Le verrouillage Mutex est le moyen le plus basique d'implémenter des verrous dans Golang. Le package de synchronisation est fourni dans Golang et le type sync.Mutex est un verrou mutex. Les verrous mutex fournissent deux méthodes : Lock() et Unlock(). La méthode Lock() est utilisée pour acquérir un verrou. Si le verrou a été acquis par une autre goroutine, la goroutine bloquera en attendant que le verrou soit libéré ; la méthode Unlock() est utilisée pour libérer le verrou. n'a pas été acquis, l'appel de la méthode Unlock() provoquera une panique à l'exécution. Un exemple est le suivant :

import "sync"

var lock sync.Mutex

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

2. Verrouillage en lecture-écriture

L'inconvénient du verrouillage mutex est qu'il est exclusif, c'est-à-dire qu'un seul goroutine peut acquérir le verrou en même temps, et les autres goroutines doivent attendre. Cela représente un gaspillage considérable pour les scénarios où il y a beaucoup de lectures et peu d'écritures, car les opérations de lecture ne modifient pas les données partagées et devraient pouvoir être effectuées en même temps. Pour résoudre ce problème, Golang fournit des verrous en lecture-écriture. Les verrous en lecture-écriture ont deux états : l’état de lecture et l’état d’écriture. Dans l'état de lecture, plusieurs goroutines peuvent acquérir des verrous de lecture-écriture en même temps, et dans l'état d'écriture, une seule goroutine peut acquérir le verrou de lecture-écriture. Les verrous en lecture-écriture fournissent trois méthodes : RLock(), RUnlock() et Lock(). La méthode RLock() est utilisée pour acquérir le verrou de lecture. Si une ou plusieurs goroutines ont acquis le verrou de lecture à ce moment-là, la nouvelle goroutine peut directement acquérir le verrou de lecture, sinon elle se bloquera et attendra que le verrou de lecture soit libéré. ; la méthode RUnlock() est utilisée pour libérer le verrou de lecture ; la méthode Lock() est utilisée pour acquérir le verrou d'écriture. Si une goroutine a acquis le verrou de lecture ou d'écriture à ce moment-là, la nouvelle goroutine bloquera l'attente du verrou. à libérer ; la méthode Unlock() est utilisée pour libérer le verrou en écriture. Un exemple est le suivant :

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. Variable de condition

La variable de condition est une primitive de synchronisation avancée, qui fournit un mécanisme qui permet à goroutine d'attendre ou de notifier qu'un événement se produit. Les variables de condition dans Golang peuvent être implémentées via le type Cond dans le package de synchronisation. Le type Cond propose trois méthodes : Wait(), Signal() et Broadcast(). La méthode Wait() est utilisée pour attendre une notification dans la file d'attente de la variable de condition. Lorsque la notification est reçue, la méthode Wait() réacquérira automatiquement le verrou ; la méthode Signal() est utilisée pour envoyer une notification à un. goroutine dans la file d'attente pour être notifié. La goroutine reviendra de la méthode Wait() ; la méthode Broadcast() est utilisée pour envoyer des notifications à toutes les goroutines dans la file d'attente, et la goroutine notifiée reviendra de la méthode Wait(). . Un exemple est le suivant :

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)
}

Résumé

En présentant en détail l'implémentation des verrous Golang, nous pouvons comprendre que les verrous fournis dans Golang sont divisés en trois types : les verrous mutex, les verrous en lecture-écriture et les variables de condition. Les verrous mutex conviennent à un accès exclusif aux données partagées, les verrous en lecture-écriture conviennent à la lecture de plus et à l'écriture de moins, et les variables de condition conviennent aux scénarios d'attente et de notification. Dans le développement réel, nous devons choisir les verrous appropriés en fonction de scénarios spécifiques pour garantir l'exactitude et les performances des opérations simultanées.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn