RSS Telegram YouTube Apple Яндекс Spotify Google Amazon Почта

17. Конкаренси, параллелизм, асинхронщина

16.09.2023

Скачать

К списку выпусков

Конкурентность

Конкурентность описывает процессы, происходящие не в один и тот же момент, но в рамках определенного промежутка времени. Это отличается от последовательности, где действия происходят друг за другом. Взяв за пример судебные решения, можно рассмотреть конкурентные и последовательные приговоры. В контексте конкурентности осужденный отбывает наказание за все деяния сразу, в рамках одного временного периода.

Термин "одновременно" в русском языке часто ассоциируется с мгновенными действиями, происходящими в один момент. Однако конкурентность не обязательно подразумевает совпадение по времени; важен общий временной интервал. Пример: возможные побочные реакции при конкурентном приеме медикаментов, когда одно лекарство принимается утром, а другое — вечером.

Для англоговорящих специалистов понятие конкурентных процессов на устройстве с одним CPU может быть интуитивно понятно. На русском языке это может вызвать затруднение, так как кажется невозможным выполнение нескольких задач одновременно с одним процессором. Но, как и в примере с медикаментами, конкурентные процессы развертываются в течение определенного времени, а не в одно и то же мгновение.

Параллелизм — это именно моментальное одновременное выполнение задач, как, например, на разных ядрах процессора. Конкурентные задачи могут быть выполнены параллельно, но это не является обязательным условием.

Сопутствующей концепцией с конкурентностью часто является синхронизация, что в контексте данной дискуссии указывает на временную координацию процессов, обеспечивающую предсказуемый доступ к общим данным и предотвращающую их повреждение из-за неожиданных конфликтов доступа.

Слово "синхронизация" произошло от греческого "хронос", что обозначает "время", подчеркивая, что упорядочивание процессов происходит именно по временной оси, а не в пространственной. В языке программирования Go есть пакет sync, включающий различные инструменты синхронизации для эффективной координации процессов.

Возникает вопрос о необходимости синхронизации, особенно когда речь идет о конкурентных процессах на одноядерном CPU. Казалось бы, один процессор не может обеспечить одновременный доступ двух процессов к данным, исключая вероятность повреждения данных. Однако, синхронизация остается важной из-за механизма работы потоков (threads), которые управляются операционной системой. Потоки работают с общей памятью и могут вмешиваться в изменения друг друга, что создает потребность в синхронизации.

Кроме конкурентности и синхронизации, другие важные понятия — синхронный и асинхронный ввод-вывод (I/O). Синхронный I/O, или блокирующий, характеризуется тем, что вызывающая функция ожидает завершения I/O операции, в то время как CPU остается неактивным. Это порождает желание оптимизировать время, используя его для выполнения других задач. В ответ на это, асинхронный I/O позволяет вызывающей функции продолжить выполнение кода, не ожидая завершения I/O операции.

Также стоит отметить, что термины "синхронный" и "асинхронный" уже не ограничиваются только областью I/O; с помощью конструкций async/await можно реализовать асинхронность для любой функции. Для обработки результатов вызванных функций существуют два распространенных метода: через коллбеки или через await. В случае использования коллбеков, функция-коллбек вызывается по завершению I/O операции. С другой стороны, при использовании await, вызывающая функция "замораживается" до момента завершения I/O операции.

В Go подход к асинхронности отличается: вместо async/await там используются горутины и каналы. Это, как мне кажется, упрощает разработку конкурентных программ, поскольку в Python с async/await часто приходится "прыгать" между функциями для понимания логики исполнения.

К списку выпусков