Concurrency Patterns
Introduction to Concurrency Patterns
Concurrency patterns provide structured approaches to solving complex concurrent programming challenges using channels in Golang.
Common Channel Concurrency Patterns
1. 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 Pattern
Pattern |
Description |
Use Case |
Fan-Out |
Single channel distributed to multiple workers |
Parallel processing |
Fan-In |
Multiple channels consolidated into single channel |
Result aggregation |
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. 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
}
Advanced Concurrency Patterns
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
}
Concurrency Pattern Best Practices
- Use channels for communication
- Avoid sharing memory
- Design for predictability
- Handle channel closure gracefully
LabEx Concurrency Insights
At LabEx, we recommend practicing these patterns through progressive complexity exercises to master concurrent programming techniques.
Conclusion
Effective concurrency patterns enable:
- Scalable system design
- Efficient resource utilization
- Clean, maintainable concurrent code