Синхронизация

Последнее обновление: 12.01.2018

Использование каналов открывает нам возможности по синхронизации между различными горутинами. Например, одна горутина производит некоторое действие, результат которой используется в другой горутине. В этом плане мы можем использовать каналы для синхронизации. Например, одна горутина вычисляет факториал числа, а результат выводится в другой горутине:

package main
import "fmt"

func main() { 
   
   intCh := make(chan int)
 
   go factorial(5, intCh)
   
   fmt.Println(<-intCh)
}

func factorial(n int, ch chan int){
	result := 1
	for i:=1; i <= n; i++{
		result *= i
	}
	ch <- result
}

Канал не обязательно должен нести данные, которые представляют некоторый результат, от которого зависит дальнейшее выполнение горутины. Иногда это может быть холостой объект, например, пустая структура, которая необходима только для синхронизации горутин:

package main
import "fmt"

func main() { 
   
   results := make(map[int]int)
   structCh := make(chan struct{})
 
   go factorial(5, structCh, results)
   
   <-structCh		// ожидаем закрытия канала structCh
   
   for i, v := range results{
	fmt.Println(i, " - ", v)
   }
}

func factorial(n int, ch chan struct{}, results map[int]int){
	defer close(ch)		// закрываем канал после завершения горутины
	result := 1
	for i:=1; i <= n; i++{
		result *= i
		results[i] = result
	}
}

В данном случае функция factorial по-прежнему вычисляет факториал, но помещает все факториалы чисел от 1 до n в отображение results, где ключи представляют числа, а значения - факториалы чисел.

Канал, через который горутины взаимодействуют, представляет тип chan struct{}. Причем функция factorial не отправляе конкретные данные в канал, а просто закрывает его после выполнения всех своих инструкций с помощью вызова defer close(ch). После закрытия канала в функции main получает соответствующий сигнал в строке <-structCh, и после этого функция main продолжает свою работу.

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850