Python. Параллельные потоки. Часть 1.
Запись от Фаер размещена 30.09.2012 в 15:34
Показов 33142
Комментарии 14
|
Параллельные потоки - вещь полезная и даже интересная, но почувствовать всю их мощь можно, только работая с большими программами и граф. интерфейсами. Большие программы Мы рассматривать не будем, чтобы не забивать голову сторонними предметами, а поэкспериментируем с мелочью. Но сначала немного теории. GIL(Global Interpreter Lock) - глобальная блокировка интерпретатора. Это понятие не слишком важно для тех, кто не хочет лезть в самую суть параллельных потоков, но кратко ознакомиться с ним всё-же не помешает. На самом деле, большая часть задач, выполняемых компьютером одновременно, не так уж и одновременна. В частности, из-за GIL Мы попадаем в такую ситуацию: в конкретный момент времени интерпретатор выполняет лишь один поток. Параллельность достигается за счёт быстрой смены выполняемых потоков, настолько быстрой (обычно каждые 0.05 сек.), что возникает ощущение одновременности выполнения операций. Таким образом, блокировка не позволяет использовать преимущества многопроцессорных систем, но это недоразумение можно обойти с помощью параллельных процессов, которые Мы разберём через урок. Модуль _thread Данный модуль позволяет запускать параллельный поток с помощью функции start_new_thread(). Поток, в Нашем случае, так же представляет собой функцию.
Обратите внимание, функции start_new_thread() мы передаём два аргумента: непосредственно функцию, которую Мы хотим запустить в параллельном потоке, и кортеж аргументов, которые эта функция принимает. В Нашем случае, передавать какие-либо данные в функцию hel() не нужно. После вызова start_new_thread() интерпретатор "параллельно" выполняет два потока: 1-ый продолжает выполнять команды, стоящие после start_new_thread()(основной поток). 2-ой выполняет команды, находящиеся в функции hel()(дочерний поток). Время от времени Нам может требоваться подождать завершения одного из потоков. Как раз для таких случаев в модуле _thread имеются блокировки.
1. Запускается параллельный поток. Основной поток ждёт пока блокировка l не будет "замкнута"(l.locked()). 2. После окончания выполнения функции hel(), Мы "замыкаем" блокировку с помощью метода acquire(). 3. Основной поток получает информацию о том, что параллельный поток был остановлен(l.locked()) и продолжает выполнять команды. Но это ещё не всё. Выполнение потока можно приостановить, а потом продолжить. Для этого Нам понадобится та же самая блокировка.
Кроме всего этого, поток можно завершить, передав соответствующую команду в нём же. Грубо говоря, поток завершит сам себя:
| ||||||||||||||||||||
Размещено в Без категории
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Всего комментариев 14
Комментарии
-
Жаль спасибо нельзя в блоге поставить.Запись от bodrich размещена 30.09.2012 в 21:48
-
Запись от Фаер размещена 01.10.2012 в 17:51
-
Запись от akzo размещена 16.08.2015 в 21:11
-
Запись от Avazart размещена 17.08.2015 в 15:13
-
Запись от tezaurismosis размещена 18.08.2015 в 10:09
-
Запись от Фаер размещена 18.08.2015 в 13:30
-
Запись от Avazart размещена 18.08.2015 в 13:39
-
Выигрыш потоков состоит в самом механизме, а не в производительности. Вы можете использовать псевдо-параллельность для удобства пользователя(ну, или себя).
Сообщение от Avazart
А вот для повышения производительности, да, стоит использовать процессы(из-за GIL. Если его нет, то и потоки распараллелятся), но при этом нужно учитывать, что процесс памяти занимает гораздо больше, управляться с ним сложнее, коммуникации между процессами напряжённы, и переключаются процессы дольше. Так что для распараллеливания(вообще) нужна веская причина, а то они только в минус загонят производительность. И сам механизм, по большому счёту, актуален лишь для многоядерных\многопроцессорных систем.
Кстати, я как-то раз проводил эксперимент. Чекал список из нескольких миллиардов элементов на Python4Android, у меня получалось, что два потока работают на четверть быстрее, чем один. Три тащили примерно так же, а вот при большем кол-ве время выполнения увеличивалось. Так что производительность(в том числе потоков) - это тоже, такой вопрос, который сильно от ситуации зависит. Нагрузку ещё надо правильно распределять.
Запись от Фаер размещена 18.08.2015 в 14:08
-
Запись от Фаер размещена 18.08.2015 в 14:11
-
Если нет производительность, то в чем тогда удобство? Тогда уже легче не разделать а делать последовательно, смысл?
Да если не дает произвоидтельности, то почему это называет потоками?
Именно по этому нужны реальные потоки, а не "механизм" или не понятное "удобство"
Мм а у вас стоит комп из каменного века с одним ядром?
Банальная задача выполнить 5000 HTTP-запросов? Как будете решать?Запись от Avazart размещена 19.08.2015 в 00:06
-
Мне эта статья пригодилась когда надо было связать два компа по TCP, нужно было чтоб ввод сообщения и вывод приходящего происходили паралельно(ну или чтобы это так казалось). Без потоков приходилось ждать пока придет сообщение и только потом отправлять свое. Так что в некоторых ситуациях это вполне удобно.
Сообщение от Avazart
Запись от akzo размещена 19.08.2015 в 19:07
-
Да уж конечно. После каждой строки кода ставить команду на обновление списка файлов? Или короткую прослушку сокета? Или ещё что-нибудь в этом роде? Так не пойдёт.
Сообщение от Avazart
Потоки нужны, когда нужны, а не когда лишь бы влепить, чтобы показать свою опытность.
Сообщение от Avazart
akzo, собственно, привёл достойный пример. :like:Запись от Фаер размещена 20.08.2015 в 18:53
-
И что это был за проект? Хеллоувордный чат?
Сообщение от akzo
Обычно как раз нужно поддерживать последовательность операций при общении запрос-ответ и тогда как раз логично именно ждать ответа...
Предположу что решение с нормальными потоками было бы куда лучше и эффективнее.
Да, по крайней мере обновление будет происходить именно там где вы это указали, а не по воли "распределения".
Как раз таки этот костыль в виде псевдо потоков вряд ли куда можно влепить.
Сообщение от Фаер
А вот прирост в производительности всегда актуален, а надлежащий средств для этого не предусмотрено в Python.Запись от Avazart размещена 20.08.2015 в 23:31
-
а как сделать так, чтобы оба потока выполнялись в одно и то же время? (мне нужно, чтобы в основном потоке задавался вопрос, а в дочернем шел таймер, и, когда оставалось 0 секунд, программа писала, что ты не успел)Запись от Slanix размещена 10.04.2017 в 19:37




