Dies ist mein erster und zweiter Beitrag als Ingenieur. Ich hatte die Gelegenheit, einen exklusiven Kontrollmechanismus in Go zu schreiben, also werde ich ihn aufzeichnen. Dieses Mal werden wir einen exklusiven Kontrollmechanismus mit zwei Methoden erstellen.
Dieses Mal wird unter Verwendung einer bestimmten Tabelle als gemeinsam genutzte Ressource bei der Verarbeitung der Tabelle aus mehreren Prozessen ein Mechanismus erstellt, der verhindert, dass nachfolgende Prozesse die Tabelle betreiben, bis der vorherige Prozess abgeschlossen ist. Ich werde fortsetzen.
Versuchen Sie zunächst, die Tabelle gleichzeitig mit der Goroutine zu aktualisieren, ohne eine ausschließliche Kontrolle durchzuführen. (sync.WaitGroup dient zum Warten auf die Haupt-Goroutine. Weitere Informationen hier.)
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 %
Sie können sehen, dass die beiden Prozesse die Tabelle gleichzeitig aktualisieren. Dieses Mal erstellen wir einen Mechanismus, um die folgende Ausgabe zu erhalten, sodass die nachfolgende Aktualisierung nach Abschluss der vorherigen Aktualisierung durchgeführt wird.
// tbl update: 0 %
// tbl update: 50 %
// tbl update: 100 %
// tbl update: 0 %
// tbl update: 50 %
// tbl update: 100 %
Zunächst von sync.Mutex.
//Die Hauptfunktion ist die gleiche wie oben
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 %
Deklarieren Sie "UnLock ()" und "Lock ()" zu Beginn von "update ()". Nachfolgende Goroutinen können "Lock ()" erst anwenden, wenn die vorhergehenden Goroutinen "UnLock ()" (bis die Verarbeitung der Funktion abgeschlossen ist) sind. Infolgedessen warten sie, bis die Verarbeitung der vorhergehenden Goroutinen abgeschlossen ist. Sie können sehen, dass die Ausgabe wie beabsichtigt ist.
sync.Mutex ist sehr einfach und unkompliziert, führt jedoch nur einen Prozess aus. Es unterscheidet sich ein wenig von diesem Szenario, aber es scheint schwierig zu sein, einen Mechanismus wie "um die Belastung des Servers zu verringern und zu verhindern, dass mehr als 1000 Prozesse gleichzeitig ausgeführt werden" zu erstellen.
Da ich zum ersten Mal ein Semapho benutze, werde ich darüber schreiben, was ein Semafo ist.
Semafo ist einer der exklusiven Kontrollmechanismen und modelliert den Betrieb von Eisenbahnstrecken. (Semaphor bedeutet auf Japanisch Signal) Es wurde erstellt, um die gemeinsam genutzte Ressource von Zeilen so zu steuern, dass sie nicht gleichzeitig verwendet werden. Ein Semapho besteht aus drei Semaphovariablen, einer P-Operation und einer V-Operation.
Dieses Szenario ist ein binäres Semapho, und es scheint notwendig zu sein, die P-Operation zu Beginn der "update ()" - und die V-Operation am Ende auszuführen.
golang.org/x/syncを使って実装します。
const semaphoreCnt = 1
var s *semaphore.Weighted = semaphore.NewWeighted(semaphoreCnt)
func update() {
defer w.Done()
defer s.Release(1) //V-Betrieb Erhöhen Sie die Semapho-Variable um 1.
s.Acquire(context.TODO(), 1) //P-Operation: Verringern Sie die Semaphovariable um 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操作にあたります。
Die exklusive Steuerung wird realisiert, indem eine Semaphovariable mit "semaphore.Weighted" definiert und mit "Acquire ()" und "Release ()" erhöht oder verringert wird.
また、golang.org/x/sync
では、Acquire()
,Release()
でセマフォ変数をいくつ増減させるかを調節することが出来ます。(今回は2値セマフォのため、それぞれ1増減となっています。)
Auf diese Weise können Sie die Verarbeitungsgewichte für jeden Prozess definieren.
golang.org/x/sync
を使うことでsync.Mutex
と比べ、より複雑な排他制御の仕組みを作ることができます。