Maison >développement back-end >Golang >Savant! Utiliser des canaux tamponnés comme mutex
Dans le cadre du package Go officiel, le package sync contient la déclaration suivante :
Le package sync fournit des primitives de synchronisation de base, telles que les verrous mutex. À l'exception des types Once et WaitGroup, la plupart des autres types sont destinés à la bibliothèque de fonctions sous-jacente. La synchronisation de niveau supérieur est mieux réalisée via les canaux et les communications.
Dans la grande majorité des exemples d'autorisation d'accès simultané, beaucoup utilisent des mutex pour résoudre le problème. Cependant, il existe peu d’exemples nous montrant comment utiliser les canaux pour fournir des mécanismes de synchronisation. Alors parlons-en dans cet article.
Pour que le verrouillage mutex fonctionne, il doit être verrouillé lors de l'accès à la variable partagée, et il doit être déverrouillé une fois l'opération terminée. Le même mutex ne peut pas être verrouillé plusieurs fois pour éviter des conditions de concurrence.
S'il n'y a pas de récepteur, l'expéditeur bloquera de la même manière, s'il n'y a pas d'expéditeur, le récepteur bloquera. Sur la base de cette caractéristique, nous ne pouvons pas utiliser de canaux non tamponnés comme verrous.
Voyons si le canal tampon peut être utilisé comme verrou mutex.
Un canal avec une taille de buffer de 1 a les caractéristiques suivantes : si le buffer est plein, l'envoi sera bloqué si le buffer est libéré ; , l'envoi sera bloqué Débloquer.
Évidemment, les caractéristiques de blocage de ce canal sont souhaitables. Comparez-les avec les caractéristiques des verrous mutex :
Lorsque le tampon est plein71fb34173e4ee87dab1f85dc1c283a44 fonctionnalité via le code.
Nous supposons qu'il y a une colonne de noms qui doivent être écrits dans le fichier, et chaque nom doit être écrit 1000 fois en continu, et aucune intersection de noms différents n'est autorisée.
package main import ( "errors" "fmt" "os" "sync" ) func main() { file, err := os.Create("record.txt") defer func() { if err := recover(); err != nil { fmt.Printf("Error encounter: %w", err) } file.Close() }() if err != nil { panic(errors.New("Cannot create/open file")) } ss := []string{ //string slice literals "James", "Avery", "Peter", "John", "Beau", } chanLock := make(chan int, 1) //1 var wg sync.WaitGroup for _, str := range ss { //2 wg.Add(1) //amended thanks to response from Wang //Sheng go func(aString string) { chanLock <- 1 //3 for i := 0; i < 1000; i++ { file.WriteString(aString + "\n") } <-chanLock //4 wg.Done() //5 }(str) //pass by value } wg.Wait() }
Dans le code ci-dessus, //1 nous créons un canal avec un tampon de 1. //2 Nous avons créé le même nombre de goroutines que de noms. //3 équivaut au verrouillage, //4 équivaut au déverrouillage, de sorte que plusieurs goroutines puissent écrire des noms dans le fichier record.txt de manière synchrone, mais une seule goroutine exploitera le fichier à la fois.
Il convient de noter que nous utilisons WaitGroup pour garantir que la goroutine principale ne se fermera pas avant que la goroutine enfant n'ait terminé la tâche.
J'espère que cet article vous sera utile, bon codage !
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!