C'est mon premier et mon deuxième poste d'ingénieur. J'ai eu l'occasion d'écrire un mécanisme de contrôle exclusif en Go, je vais donc l'enregistrer. Cette fois, nous allons créer un mécanisme de contrôle exclusif en utilisant deux méthodes.
Cette fois, en utilisant une certaine table comme ressource partagée, lorsque le traitement est effectué sur la table à partir de plusieurs processus, un mécanisme est créé pour empêcher les processus suivants de faire fonctionner la table jusqu'à ce que le processus précédent soit terminé. Je vais continuer.
Tout d'abord, essayez de mettre à jour la table en même temps en utilisant le goroutine sans effectuer de contrôle exclusif. (sync.WaitGroup est pour attendre la goroutine principale. Pour plus d'informations ici.)
var w sync.WaitGroup
func main() {
w.Add(2)
go update()
go update()
w.Wait()
}
func update() {
defer w.Done()
for i := 0; i <= 10; i += 5 {
fmt.Println("tbl update:", i*10, "%")
time.Sleep(time.Second)
}
}
// tbl update: 0 %
// tbl update: 0 %
// tbl update: 50 %
// tbl update: 50 %
// tbl update: 100 %
// tbl update: 100 %
Vous pouvez voir que les deux processus mettent à jour la table en même temps. Cette fois, nous allons créer un mécanisme pour obtenir la sortie suivante afin que la mise à jour suivante soit effectuée une fois la mise à jour précédente terminée.
// tbl update: 0 %
// tbl update: 50 %
// tbl update: 100 %
// tbl update: 0 %
// tbl update: 50 %
// tbl update: 100 %
Tout d'abord, depuis sync.Mutex.
//La fonction principale est la même que ci-dessus
var m sync.Mutex
func update() {
defer w.Done()
defer m.Unlock()
m.Lock()
for i := 0; i <= 10; i += 5 {
fmt.Println("tbl update:", i*10, "%")
time.Sleep(time.Second)
}
}
// tbl update: 0 %
// tbl update: 50 %
// tbl update: 100 %
// tbl update: 0 %
// tbl update: 50 %
// tbl update: 100 %
Déclarez «UnLock ()» et «Lock ()» au début de «update ()».
Les goroutines suivantes ne peuvent pas appliquer Lock ()
jusqu'à ce que les goroutines précédentes UnLock ()
(jusqu'à ce que le traitement de la fonction soit terminé), et par conséquent, elles vont attendre que le traitement des goroutines précédentes se termine.
Vous pouvez voir que la sortie est comme vous le souhaitiez.
sync.Mutex est très simple et direct, mais il ne fait qu'un seul processus. C'est un peu différent de ce scénario, mais il semble difficile de créer un mécanisme tel que "pour réduire la charge sur le serveur, empêcher plus de 1000 processus de s'exécuter en même temps".
Puisque c'est la première fois que j'utilise un semapho, j'écrirai sur ce qu'est un semafo.
Semafo est l'un des mécanismes de contrôle exclusifs et modélise l'exploitation des lignes ferroviaires. (Sémaphore signifie signal en japonais) Il a été créé pour contrôler la ressource partagée des lignes afin qu'elles ne soient pas utilisées en même temps. Un semapho se compose de trois variables de semapho, une opération P et une opération V.
--Variable Mapho --Nombre de processus pouvant accéder aux ressources partagées ――Ce ne sera pas négatif --Une variable sémapho qui ne prend que 0 ou 1 est appelée un ** semapho binaire (sémapho binaire) **, et une variable qui prend 0 à N est appelée un ** semapho général **. --P opération --Décrémenter la variable semapho --Un processus sécurise les ressources partagées -V opération --Incrémenter la variable semapho --Un processus libère des ressources partagées
Ce scénario est un semapho binaire, et il semble qu'il soit nécessaire d'effectuer l'opération P au début de update ()
et l'opération V à la fin.
golang.org/x/syncを使って実装します。
const semaphoreCnt = 1
var s *semaphore.Weighted = semaphore.NewWeighted(semaphoreCnt)
func update() {
defer w.Done()
defer s.Release(1) //Opération V Augmentez la variable semapho de 1.
s.Acquire(context.TODO(), 1) //Opération P: Diminuez la variable semapho de 1.
for i := 0; i <= 10; i += 5 {
fmt.Println("tbl update:", i*10, "%")
time.Sleep(time.Second)
}
}
// tbl update: 0 %
// tbl update: 50 %
// tbl update: 100 %
// tbl update: 0 %
// tbl update: 50 %
// tbl update: 100 %
golang.org/x/sync
のAcquire()
がP操作に,Release()
がV操作にあたります。
Le contrôle exclusif est réalisé en définissant une variable semapho avec semaphore.Weighted
et en l'augmentant ou en la diminuant en utilisant Acquire ()
etRelease ()
.
また、golang.org/x/sync
では、Acquire()
,Release()
でセマフォ変数をいくつ増減させるかを調節することが出来ます。(今回は2値セマフォのため、それぞれ1増減となっています。)
Cela vous permet de définir les poids de traitement pour chaque processus.
golang.org/x/sync
を使うことでsync.Mutex
と比べ、より複雑な排他制御の仕組みを作ることができます。