Повесть об этом стара, но слава нетленна (Вергилий).

Лучший способ изучить Python (пошаговое руководство 2020 года). Часть 3

FavoriteLoadingДобавить в избранное
1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд (1 оценок, среднее: 5,00 из 5)
Загрузка...
20 апреля 2020
Как установить Python 3 на Ubuntu 16.04 LTS

Уровень 2: совместное и параллельное программирование

Дни одноядерных процессоров давно прошли.

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

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

Это может привести к увеличению пропускной способности, повышению производительности и повышению скорости отклика.

Но позвольте нам прояснить одну вещь.

Если высокая производительность и увеличенная пропускная способность абсолютно необходимы, Python не будет лучшим языком для поддержки параллельного программирования.

В этой ситуации мы лично предпочли бы вместо его golang (или старый добрый C ).

Но так как это статья о Python, давайте сосредоточимся на Python.

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

Вот некоторые из этих концепций.

 

Взаимное исключение

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

Если вы этого не сделаете, может возникнуть состояние гонки, которое может привести к неожиданным, а иногда и катастрофическим последствиям. Мы расскажем больше об условиях гонки позже.

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

 

Замки

Замки являются одной из различных реализаций взаимного исключения.

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

Если поток хочет получить доступ к общему ресурсу, этот поток должен захватить блокировку, прежде чем ему будет предоставлен доступ к этому ресурсу.

И после того, как это сделано с ресурсом, он снимает эту блокировку.

Если блокировка недоступна, потому что она захвачена другим потоком, то поток должен ждать, пока блокировка будет снята первой.

Эта простая концепция гарантирует, что не более одного потока может иметь доступ к общему ресурсу одновременно.

 

Тупики

Взаимная блокировка – это когда ваша программа полностью останавливается, потому что некоторые потоки не могут развиваться дальше, потому что они не могут получить блокировку.

Например, представьте, что поток A ожидает в потоке B снятие блокировки. В то же время поток B ожидает в потоке A освобождение еще одной блокировки, которую в данный момент удерживает поток A.

В этой тяжелой ситуации ни поток A, ни поток B не могут развиваться дальше, поэтому ваша программа закрыта!

Вот что такое тупик.

И это случается чаще, чем вы думаете.

Что еще хуже, это также одна из самых сложных проблем для отладки.

 

Состязание

Как мы упоминали ранее, состояние гонки – это ситуация, которая возникает, когда доступ к общему ресурсу не защищен (например, блокировками).

Это может привести к катастрофическим неожиданным результатам.

Посмотрите на этот пример.

import threading
# x это общее значение
x = 0
COUNT = 1000000

def inc():
    global x
    for _ in range(COUNT):
        x += 1

def dec():
    global x
    for _ in range(COUNT):
        x -= 1

t1 = threading.Thread(target=inc)
t2 = threading.Thread(target=dec)
t1.start()
t2.start()
t1.join()
t2.join()

print(x)

 

Вот что делает код выше:

Существует общая глобальная переменная x, которая инициализируется в 0.

Две функции inc и dec работают параллельно. inc () увеличивает значение x 1 миллион раз, тогда как dec () уменьшает значение x 1 миллион раз.

Быстро пройдясь по коду, можно сделать вывод, что конечное значение x должно быть 0 … но так ли это?

Вот что мы получаем, когда запускаем приведенный выше код.

 $ python3 race.py
158120
 $ python3 race.py
137791
 $ python3 race.py
-150265
 $ python3 race.py
715644

 

Причина, по которой это происходит, заключается в том, что общий ресурс x не защищен (например, блокировками).

 

Параллельное программирование в Python

Только после того, как вы освоитесь с концепциями, рассмотренными выше, вы готовы научиться писать параллельные программы на Python.

Во-первых, вы должны узнать, как определение многопроцессорности в Python отличается от многопоточности. (Кстати, это совершенно не связано с потоками и процессами с точки зрения ОС ).

Чтобы понять это различие между многопроцессорностью и многопоточностью с точки зрения Python, вам необходимо изучить и понять глобальную блокировку интерпретатора (GIL).

Вам также необходимо узнать о потоках, очереди и многопроцессорных  модулях Python.

Все эти модули предоставляют вам примитивы, необходимые для написания параллельных программ.

 

Начало:

 

Продолжение

 

Продолжение следует…

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.

Если статья понравилась, то поделитесь ей в социальных сетях:

Читайте также

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам:

Заполните форму и наш менеджер перезвонит Вам в самое ближайшее время!

badge
Обратный звонок 1
Отправить
galka

Спасибо! Ваша заявка принята

close
galka

Спасибо! Ваша заявка принята

close