Курс — «Программирование на Go для начинающих» — #14 Конкурентность в Go: Горутины — основы конкурентного выполнения.
Здравствуйте, дорогие друзья.
Конкурентное программирование является ключевым аспектом современной разработки программного обеспечения, позволяя приложениям эффективно выполнять множество задач одновременно. В языке программирования Go конкурентность реализуется через горутины и каналы, предоставляя мощные и легко используемые инструменты для создания многозадачных приложений. В этом разделе мы сосредоточимся на горутинах, которые являются основой конкурентного выполнения в Go.
Что такое горутины?
Горутина — это легковесный поток выполнения, управляемый Go runtime. Горутины позволяют выполнять функции конкурентно, в рамках одного и того же процесса. Создание горутины в Go невероятно просто — достаточно использовать ключевое слово go
перед вызовом функции.
1 2 3 4 5 6 7 8 9 10 11 12 |
package main import ( "fmt" "time" ) func sayHello() { fmt.Println("Hello, world!") } func main() { go sayHello() time.Sleep(1 * time.Second) // Даем время горутине для выполнения } |
В этом примере sayHello
будет выполнена как горутина, что позволит main
продолжать выполнение без блокировки. Однако, поскольку main
также является горутиной, программа завершится, как только main
закончит свое выполнение, если не предпринять меры для ожидания завершения других горутин.
Основы работы с горутинами
Горутины предоставляют простой способ для выполнения задач параллельно. Однако, с их использованием связаны некоторые особенности:
- Легковесность: Горутины занимают гораздо меньше памяти, чем традиционные потоки ОС, и их создание стоит дешевле с точки зрения системных ресурсов.
- Динамическое управление: Go runtime автоматически управляет горутинами, распределяя их по доступным ядрам процессора.
- Синхронизация: Для синхронизации и обмена данными между горутинами используются каналы, предотвращая гонки данных и другие проблемы конкурентного доступа.
Пример использования горутин
Рассмотрим пример, где несколько горутин выполняют задачу параллельно:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
package main import ( "fmt" "sync" "time" ) func worker(id int, wg *sync.WaitGroup) { defer wg.Done() fmt.Printf("Worker %d starting\n", id) time.Sleep(time.Second) fmt.Printf("Worker %d done\n", id) } func main() { var wg sync.WaitGroup for i := 1; i <= 5; i++ { wg.Add(1) go worker(i, &wg) } wg.Wait() // Ожидаем завершения всех горутин } |
В этом примере используется sync.WaitGroup
для ожидания завершения всех горутин перед выходом из программы. Каждая горутина представляет собой «работника», выполняющего некоторую задачу.
Горутины представляют собой мощный и гибкий инструмент для реализации конкурентности в Go. Благодаря их легковесности и простоте использования, разработчики могут легко создавать высокопроизводительные и масштабируемые приложения. Важно помнить о необходимости правильной синхронизации и управления жизненным циклом горутин, чтобы избежать проблем с безопасностью данных и утечками ресурсов.
На этом все. Всем хорошего дня!
Цикл статей по курсу: «Язык программирования Go для начинающих».