Maison > Article > développement back-end > Est-ce que la langue prend en charge les verrous ?
Le langage Go prend en charge les verrous. La bibliothèque standard du langage go fournit deux types de verrous : 1. Le verrouillage mutex (sync.Mutex), qui peut protéger une ressource contre les conflits provoqués par des opérations simultanées et entraînant des données inexactes. 2. Le verrouillage en lecture-écriture (sync.RWMutex) ; Lorsque le verrou de lecture est occupé, l'écriture est bloquée, mais la lecture n'est pas bloquée. Dans un environnement avec plus de lectures et moins d'écritures, les mutex en lecture-écriture peuvent être utilisés en premier.
L'environnement d'exploitation de ce tutoriel : système Windows 7, GO version 1.18, ordinateur Dell G3.
La bibliothèque standard du langage go fournit deux verrous, l'un est un verrou mutex et l'autre est un verrou en lecture-écriture. Le package de synchronisation du package de langue Go fournit deux types de verrouillage : le verrouillage mutex (sync.Mutex) et le verrouillage en lecture-écriture (sync.RWMutex).
Le Mutex est le type de verrouillage le plus simple, et il est également relativement violent Lorsqu'une goroutine obtient un Mutex, les autres goroutines ne peuvent qu'attendre que la goroutine libère le Mutex.
RWMutex est relativement convivial et est un modèle classique d'écriture une fois, lecture multiple. Lorsque le verrou de lecture est occupé, l'écriture sera bloquée, mais la lecture ne sera pas bloquée. Autrement dit, plusieurs goroutines peuvent acquérir le verrou de lecture en même temps (appelant la méthode RLock() pendant le verrouillage d'écriture (appelant le Lock) ; ()) empêchera toute autre goroutine (que ce soit en lecture ou en écriture) d'entrer, le verrou entier équivaut à appartenir exclusivement à la goroutine. À en juger par l'implémentation de RWMutex, le type RWMutex combine en fait Mutex :
type RWMutex struct { w Mutex writerSem uint32 readerSem uint32 readerCount int32 readerWait int32 }
Pour ces deux types de verrous, tout Lock() ou RLock() doit s'assurer qu'il existe un appel Unlock() ou RUnlock() correspondant, sinon ceci peut provoquer l'épuisement de toutes les goroutines en attente du verrou, voire provoquer un blocage. [Recommandations associées : Tutoriel vidéo Go, Enseignement de la programmation] Le modèle d'utilisation typique du
lock est le suivant :
package main import ( "fmt" "sync" ) var ( // 逻辑中使用的某个变量 count int // 与变量对应的使用互斥锁 countGuard sync.Mutex ) func GetCount() int { // 锁定 countGuard.Lock() // 在函数退出时解除锁定 defer countGuard.Unlock() return count } func SetCount(c int) { countGuard.Lock() count = c countGuard.Unlock() } func main() { // 可以进行并发安全的设置 SetCount(1) // 可以进行并发安全的获取 fmt.Println(GetCount()) }
La description du code est la suivante :
La ligne 10 est une variable utilisée dans un certaine étape logique, peu importe qu'il s'agisse d'une variable au niveau du package ou d'un champ membre de la structure.
Ligne 13, en général, il est recommandé de définir la granularité du mutex la plus petite possible pour réduire le temps d'attente pour l'accès partagé. Ici, l'auteur nomme habituellement la variable mutex au format suivant :
变量名+Guard
pour indiquer que le mutex est utilisé pour protéger cette variable.
La ligne 16 est une encapsulation de fonction pour obtenir la valeur du comptage Grâce à cette fonction, la variable count est accessible simultanément et en toute sécurité.
Ligne 19, essayez de verrouiller le mutex countGuard. Une fois countGuard verrouillé, si une autre goroutine tente de continuer le verrouillage, elle sera bloquée jusqu'à ce que countGuard soit déverrouillé.
La ligne 22 utilise defer pour retarder l'appel de déverrouillage de countGuard. L'opération de déverrouillage se produira au retour de la fonction GetCount().
À la ligne 27, lors de la définition de la valeur de comptage, countGuard est également utilisé pour effectuer des opérations de verrouillage et de déverrouillage afin de garantir que le processus de modification de la valeur de comptage est un processus atomique et qu'aucun conflit d'accès simultané ne se produira.
Dans un environnement où il y a beaucoup de lecture et peu d'écriture, vous pouvez privilégier l'utilisation d'un mutex en lecture-écriture (sync.RWMutex), qui est plus efficace qu'un mutex. RWMutex dans le package sync fournit une encapsulation des mutex en lecture-écriture.
Nous avons modifié une partie du code dans l'exemple de mutex en un mutex en lecture-écriture, voir le code ci-dessous :
var ( // 逻辑中使用的某个变量 count int // 与变量对应的使用互斥锁 countGuard sync.RWMutex ) func GetCount() int { // 锁定 countGuard.RLock() // 在函数退出时解除锁定 defer countGuard.RUnlock() return count }
La description du code est la suivante :
Ligne 6, lors de la déclaration de countGuard, depuis sync.Mutex mutex Le verrou est remplacé par le verrou mutex en lecture-écriture sync.RWMutex.
Ligne 12, le processus d'obtention du décompte est un processus de lecture des données de décompte, qui convient aux verrous mutex en lecture et en écriture. Dans cette ligne, remplacez countGuard.Lock() par countGuard.RLock() pour marquer le mutex en lecture-écriture comme lu. Si une autre goroutine accède simultanément à countGuard et appelle countGuard.RLock() en même temps, aucun blocage ne se produira.
Ligne 15, correspondant au verrouillage du mode lecture, utilisez le mode lecture pour déverrouiller.
Remarque spéciale :
Le verrou de sync.Mutex ne peut pas être imbriqué
Le RLock() de sync.RWMutex peut être imbriqué
sync.RWMutex mu.Lock() ne peut pas être imbriqué
sync.RWMutex ne peut pas être imbriqué dans mu.RLock()
Pour plus de connaissances sur la programmation, veuillez visiter : Vidéo de programmation ! !
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!