Паттерны параллельности
Введение в паттерны параллельности
Паттерны параллельности (concurrency patterns) предоставляют структурированные подходы к решению сложных задач параллельного программирования с использованием каналов (channels) в Golang.
Общие паттерны параллельности с использованием каналов
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)
Паттерн |
Описание |
Сценарий использования |
Fan-Out |
Один канал распределяет данные между несколькими рабочими потоками |
Параллельная обработка |
Fan-In |
Несколько каналов объединяются в один канал |
Агрегация результатов |
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
}
Продвинутые паттерны параллельности
Паттерн конвейера (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
}
Лучшие практики при использовании паттернов параллельности
- Используйте каналы для коммуникации
- Избегайте общего доступа к памяти
- Проектируйте для предсказуемости
- Корректно обрабатывайте закрытие каналов
Инсайты по параллельности от LabEx
В LabEx мы рекомендуем практиковать эти паттерны с помощью упражнений постепенно возрастающей сложности, чтобы овладеть техниками параллельного программирования.
Заключение
Эффективные паттерны параллельности позволяют:
- Проектировать масштабируемые системы
- Эффективно использовать ресурсы
- Создавать чистый и поддерживаемый параллельный код