Konkurrenzmuster (Concurrency Patterns)
Einführung in Konkurrenzmuster
Konkurrenzmuster bieten strukturierte Ansätze zur Lösung komplexer Probleme in der gleichzeitigen Programmierung mit Kanälen (channels) in Golang.
Häufige Kanal-Konkurrenzmuster
1. Worker-Pool-Muster (Worker Pool Pattern)
graph LR
A[Job Queue] --> B[Worker Pool]
B --> C[Result Channel]
func workerPool(jobs <-chan int, results chan<- int) {
for job := range jobs {
results <- processJob(job)
}
}
func main() {
jobs := make(chan int, 100)
results := make(chan int, 100)
// Create worker pool
for w := 1; w <= 3; w++ {
go workerPool(jobs, results)
}
// Send jobs
for j := 1; j <= 5; j++ {
jobs <- j
}
close(jobs)
// Collect results
for a := 1; a <= 5; a++ {
<-results
}
}
2. Fan-Out/Fan-In-Muster
Muster |
Beschreibung |
Anwendungsfall |
Fan-Out |
Ein einzelner Kanal wird an mehrere Worker verteilt |
Parallele Verarbeitung |
Fan-In |
Mehrere Kanäle werden zu einem einzelnen Kanal zusammengeführt |
Ergebnisaggregation |
func fanOutFanIn() {
ch1 := make(chan int)
ch2 := make(chan int)
ch3 := make(chan int)
// Fan-Out
go func() {
for i := 0; i < 10; i++ {
ch1 <- i
ch2 <- i
}
close(ch1)
close(ch2)
}()
// Fan-In
go func() {
for {
select {
case v, ok := <-ch1:
if !ok {
ch1 = nil
}
ch3 <- v
case v, ok := <-ch2:
if !ok {
ch2 = nil
}
ch3 <- v
}
if ch1 == nil && ch2 == nil {
close(ch3)
return
}
}
}()
}
3. Semaphor-Muster (Semaphore Pattern)
type Semaphore struct {
semaChan chan struct{}
}
func NewSemaphore(max int) *Semaphore {
return &Semaphore{
semaChan: make(chan struct{}, max),
}
}
func (s *Semaphore) Acquire() {
s.semaChan <- struct{}{}
}
func (s *Semaphore) Release() {
<-s.semaChan
}
Fortgeschrittene Konkurrenzmuster
Pipeline-Muster (Pipeline Pattern)
graph LR
A[Stage 1] --> B[Stage 2]
B --> C[Stage 3]
func generateNumbers(max int) <-chan int {
ch := make(chan int)
go func() {
for i := 1; i <= max; i++ {
ch <- i
}
close(ch)
}()
return ch
}
func squareNumbers(input <-chan int) <-chan int {
ch := make(chan int)
go func() {
for n := range input {
ch <- n * n
}
close(ch)
}()
return ch
}
Best Practices für Konkurrenzmuster
- Verwenden Sie Kanäle für die Kommunikation.
- Vermeiden Sie die gemeinsame Nutzung von Speicher.
- Entwerfen Sie für Vorhersagbarkeit.
- Schließen Sie Kanäle gracefully.
LabEx-Konkurrenz-Insights
Bei LabEx empfehlen wir, diese Muster durch Übungen mit zunehmender Komplexität zu üben, um die Techniken der gleichzeitigen Programmierung zu meistern.
Fazit
Effektive Konkurrenzmuster ermöglichen:
- Skalierbares Systemdesign
- Effiziente Ressourcennutzung
- Sauberen und wartbaren gleichzeitigen Code