Горутины: конкурентная синхронизация
Конкурентные вычисления могут совместно использовать ресурсы, как правило, ресурсы памяти. Ниже приведены некоторые обстоятельства, которые могут возникнуть во время конкурентных вычислений:
-
В тот же период времени, когда одно вычисление записывает данные в сегмент памяти, другое вычисление считывает данные из того же сегмента памяти. Тогда целостность данных, считанных другим вычислением, может не сохраниться.
-
В тот же период времени, когда одно вычисление записывает данные в сегмент памяти, другое вычисление также записывает данные в тот же сегмент памяти. Тогда целостность данных, хранящихся в сегменте памяти, может не сохраниться.
Эти обстоятельства называются гонками данных. Одной из обязанностей конкурентного программирования является контроль за совместным использованием ресурсов конкурентными вычислениями, чтобы никогда не возникало гонок данных. Способы реализации этой обязанности называются конкурентными синхронизациями или синхронизациями данных.
Другие обязанности в конкурентном программировании включают:
-
определение необходимого количества вычислений;
-
определение момента, когда нужно начинать, блокировать, разблокировать и заканчивать вычисление;
-
определение того, как распределить рабочую нагрузку между конкурентными вычислениями.
Программа, показанная в последнем примере, не идеальна. Две новые горутины предназначены для печати десяти приветствий каждая. Однако основная горутина завершится через две секунды, поэтому у многих приветствий нет шансов быть напечатанными. Как сообщить основной горутине, когда две новые горутины завершили свои задачи? Мы должны использовать так называемые методы конкурентной синхронизации.
Go поддерживает несколько методов конкурентной синхронизации. Среди них канальная техника является самой уникальной и широко используемой. Однако для простоты здесь мы будем использовать другой метод — WaitGroup тип в sync стандартном пакете — для синхронизации выполнения между двумя новыми горутинами и основной горутиной.
Тип WaitGroup имеет три метода (специальные функции, которые будут объяснены позже): Add, Done и Wait.
Рассмотрим методы:
-
метод Add используется для регистрации количества новых задач;
-
метод Done используется для уведомления о завершении задачи;
-
и этот Wait метод заставляет вызывающую горутину блокироваться до тех пор, пока все зарегистрированные задачи не будут завершены.
Пример:
Пришло время поработать с кодом!
Запустив его, мы можем обнаружить, что перед выходом из программы каждая из двух новых горутин выводит десять приветствий.