Как стать автором
Обновить

Комментарии 56

Спасибо, написано здорово :)
А кто автор?
Исправил. Сначала никак не мог найти его имя, так как не подписывает статьи, подлец. :) Но потом увидел маленькую строчку в самом низу.
Для тех, кто еще не нашел: justin.harmonize.fm/index.php/2008/09/threading-model-overview/
Для тех, кто не знает: на этой странице, под статьёй, после звёздочки «избранное» как раз располагается ссылка на оригинал.
Спасибо, я не сразу заметил.
Спасибо за труд
Можно развивать тему, показать примеры и сравнения, тогда будет настоящая исследовательская работа.
Вообще говоря, развитие технологий показало что производительность будет наращиваться увеличением вычислительных узлов. Надо уже читать о кластерных вычислениях, там не все принципы многопоточности работать будут.
ПС. в блог Разработка
Да, переносите в разработку.

Жаль последний абзац скомканный немного.
Так толком и не понятно есть ли многопоточно в JavaScript или нет :)
(хотя распаралеливать задачи там можно, но насколько это будет «многопоточность», не ясно)

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

Кстати, а как с этим делом на php? а то я завно на нем уже не программирую и не слежу за новостями…

к сожалению, такого в PHP нет и вряд ли вообще будет.
Странно. Что их ограничевает? ведь Ruby смогли же.
Есть, и уже давно. См. доку по pcntl_fork
Так эта функция запускает дочерний процесс. Это «немного» не поток…
Насколько я знаю, истинной многопоточности в PHP нет.
ну а в перле разве не примерно то же самое?
С Перлом не работал, так что не знаю…
Что касается PHP, то тут написано примерно следующее:
PHP does not have threading anywhere in its massive core. We can, however, fake it by relying on the underlying operating system’s multitasking abilities instead of PHP. This article will show you how.
PHP has no built in support for threading. But there can still be times when you’ve got lengthy code to run and idle CPU cyles you’d like to capitalize on. We can treat child processes as threads.

и далее
This isn’t true multithreading. We’re just running multiple processes, and facilitating communication between them. As each thread is a separate instance or part of your application, its entry point needs to re-include all code you’d normally need: functions and classes established at the time you create a thread are not automatically visable to the new thread. Performance isn’t great, as PHP has to re-parse every file multiple times.
Нет, в перле потоки — это паралелльные вычисления в рамках одного процесса, можно расшаривать переменные между потоками для совместного использования, использовать семафоры, лочить потоки из родителя и т.д… Хотя для каждого потока стартует свой интерпретатор. Т.е. потоки в перле — это не форк.
в Perl реализована «модель потоков интерпретаторов». в обсуждаемой статье более или менее корректно описана.

треды исполняются внутри процесса и могут обращаться к общему пулу данных (уже оговаривалось что процесс является контейнером для тредов).

запуск нового интерпретатора в контексте заданном статьей не стоит путать с запуском нового /usr/bin/perl или perl.exe :) для более глубокого понимания того что подразумевается под интерпретатором требуется чтение документации. с подрбностями можно ознакомиться в книге Ларри: в разделе «компиляция» есть глава «жизненный цикл программ на Perl». в итоге получаем самые настоящие потоки

при поверхностном анализе перлового многопоточного процесса треды можно разглядеть. например в виндовом processexplorer есть вкладка threads — из одного перлового процесса торчит несколько тредов :)

дорогое удовольствие только если треды рождаются в интенсивном цикле. в остальных случаях сущий пустяк
А зачем языку изначально предназначенному исключительно для веб-разработки нужны потоки? Лично не вижу никакого функционала, на реализацию которого мне было бы необходимо использовать потоки. А если вдруг кому-то они очень понадобятся, то будет реализовывать экстеншн основынный на pthreads ^__^
неправда
Где-то видел, что собираются добавить толи с 5.3, толи в 6.0. Может это лишь слухи, не знаю.
В JavaScript нет многопоточности (http://javascript.ru/blog/tenshi/mnogopotochnyi-yavaskript).

Вообще странно, что автор (не переводчик), поставил в один ряд C# и JavaScript.
В первом с этим всё чуть-ли не идеально, в последнем же этого вообще нет.
Многие PHP-разработчики полагают, что поскольку в стандарте PHP отсутствуют возможности для обработки потоков (thread), невозможно организовать работающее многозадачное PHP-приложение. Например, если приложению нужна информация с другого Web-сайта, оно должно остановиться и подождать завершения извлечения этой удаленной информации. Это не правда! Узнайте о внутрипроцессной (in-process) многозадачности в PHP, использующей функции stream_select и stream_socket_client.

www.ibm.com/developerworks/ru/library/os-php-multitask/index.html
Только это называется не «многозадачность», а «асинхронный ввод-вывод». Две большие разницы.
>а «асинхронный ввод-вывод»
select — это «неблокирующий ввод-вывод» (reactor) — приходит эвент о том что можно читать данные
«асинхронный ввод-вывод» (proactor) — делаешь запрос на чтение и система оповещает что прочитала и записала в буффер
p.s. под select'ом — я имел в виду тот кусочик кода, который описан по ссылке выше :) а не сам вызов селекта, понимаю что это просто способ дожидаться эвентов, и там могут приходить как неблокирующие i/o эвенты, так и асинхронные…
Да, с такой поправкой согласен. Спасибо. :)
select — это мультиплексированный ввод-вывод. Его вызов всё таки блокирует программу, пока один из дискрипторов не будет готов к чтению. А если задать таймайт то это будет polling т. е. опрос.
и насколько я понял ту статью, там с помощью proc_open создают новые процессы, которые всё же попадают под понятие «многозадачность», а далее основным процессом с помощью «неблокирующего ввода-вывода» дожидаются от них результатов…
переключение между нэйтив потоками дороже потому что переключение происходит через вход в режим ядра и выход из него.
Существует смешанная реализация. Потоки работают в режиме пользователя, но при системных вызовах переключаются в режим ядра. Переключение в режим ядра и обратно является ресурсоемкой операцией и отрицательно сказывается на производительности системы. Поэтому было введено понятие волокна — облегченного потока, выполняемого исключительно в режиме пользователя. У каждого потока может быть несколько волокон. Подобный тип многопоточности реализован в ОС Windows.
[WIKI]
>Подобный тип многопоточности реализован в ОС Windows.
и не только :)
gnu portable threads — www.gnu.org/software/pth/
ещё более легковесные
protothreads — www.sics.se/~adam/pt/
итд…
Следует добавить, что примитивы синхронизации для легковесных потоках работают только в пределах одного процесса.
наверное потому что планировщик тоже внутри процесса расположен, да?
Не сам планировщик, а та часть, которая отвечает за синхронизацию. Потому как Mutex, Events вызывают функции ядра. Кстати онные примитивы отлично подходят чтобы реализовать синхронизацию user mode и kernel mode кода. А, к примеру, CriticalSection основана на примитивном механизме spin lock, реализовать который можно в самом процессе.
CriticalSection это только виндоус прикол? :) реализуется насколько я понимаю просто установкой пользовательского мьютекса?
Интересная статья. Хотелось бы дополнения, конечно. Не совсем понятно как выглядит ситуация с потоками в функциональных языках (только Erlang и то, поверхностно), а ведь основную мощь «функциональные» программы приобретают при многопоточном исполнении.
Не знаю как там сейчас с ерлангом, но раньше было так — запускают нэтив трэды по кол-ву логических процессоров, далее пораждают свои легковесные процессы, в которых есть счётчик bif'ов(простые функции), после того как они выполняют отведёное для процесса число bif'ов, переключаются на другой процесс.
кстати, erlang не полностью shared nothing(см. документацию на ets)
Насколько я понял из обсуждения полугодичной давности, в Erlang свой менеджер потоков, т.е. что-то типа green threads.
Вот интересная статья про многопоточность в РНР
php.webconsulting.by/2008/05/02/mnogopotochnost-v-php-unix-funkciya-fork/
В Python 3k/2.6 проблему GIL и SMP решили кардинально: docs.python.org/dev/library/multiprocessing.html Ж)))
Сильно. Ждём Singularity/Midori, в которой это будет летать. :)
А что, в линуксе порождение процессов недостаточно быстрое?
Хорошо придумал: вот вам статья, но если она показалось вам поверхностной, то мопед не мой, я только разместил объяву :)

Кроме того, имеются неточности в самой статье:

> принципе, поток — это процесс, который исполняется на выделенном процессоре, выполнение которого контролирует планировщик (scheduler) ОС, и который может быть заблокирован.

Поток — это не процесс, я думаю тут мешанина из терминов получилась. Лучше написать, что поток — это процесс выполнение на процессоре инструкций и т.д.

> Linux позволяет использовать данные потоки с помощью библиотеки pthread. BSDs тоже поддерживает pthreads. Потоки Windows работают аналогично.

Нууу, кто использовал pthreads и потоки win32, тот знает, что разница в их работе разительна. Например pthreads не умеют делать suspend/resume, win32 потоку нельзя сделать cancel, как в pthread, его можно только нелегальным образом убить. Также средства синхронизации разительно отличаются. Events нет в posix, conditional variables нет в win32 (только в висте) и т.д. То что и pthreads и win32 потоки — preemptive, зависит от операционной системы, а не от поточной модели. Далее можно было рассказать о preemptive и cooperative потоках.

А так, еще один интересный факт. Carbon фреймворк на Mac OS X использует свой трид менеджер, который реализует cooperative модель, когда сама Mac OS X использует preemptive.
Процесс не выполняется на процессоре (он служит контейнером потоков). Процесс — группирует ресурсы (адресное пространство, потоки, ресурсы). Поток — исполняется на процессоре. Каждый процесс состоит хотя бы из одного потока. Процессы изолированы друг от друга, а потоки (находящиеся внутри одного процесса) могут использовать одно и тоже АП.

>поток — это процесс, который исполняется на выделенном процессоре
А если у меня процессор только один, значит в системе может быть только один поток? Мне кажется статья скорее запутает, чем прояснит ситуацию, т.к. в ней полно неточностей (возможно, дело не в переводе).
Да, «поток — это процесс» сильно режет по ушам.
> Хорошо придумал: вот вам статья, но если она показалось вам поверхностной, то мопед не мой, я только разместил объяву :)

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

> Поток — это не процесс, я думаю тут мешанина из терминов получилась.

Cам морщился.

> Нууу, кто использовал pthreads и потоки win32, тот знает, что разница в их работе разительна…

Вот это я и называю полезным комментарием. Тема интересная и «вечная». Почему бы не сделать более качественную статью по этой теме? Лично я буду рад почитать.
А так, еще один интересный факт. Carbon фреймворк на Mac OS X использует свой трид менеджер, который реализует cooperative модель, когда сама Mac OS X использует preemptive.

Это наверное потому, что в Mac OS Classic была только кооперативная модель, а карбон в первую очередь предназначен для легкого портирования приложений из Classic в OS X.

… да, кстати: thread = [θred], not [θri: d]
… да, кстати: thread = [θred], not [θri: d]

Люто, неистово плюсую. Что «триды», что «хидеры», как пенопластом по стеклу :(
НЛО прилетело и опубликовало эту надпись здесь
Не ковыяй в носу, детей не будет! Да я неглубоко! ©УПИ
А наскольку глубоко, хотелось некоторым?:)
НЛО прилетело и опубликовало эту надпись здесь
Ruby 1.9 опирается на системные потоки + GIL.
Точнее, там дело даже не в GIL'е. Некоторые из нативных библиотек не рассчитаны на многопоточность, поскольку ее во время их написания не ожидалось, поэтому полноценная параллельность пока что зарезана искусственно. Но над этим работают.
НЛО прилетело и опубликовало эту надпись здесь
стало интересно какие потоки имеют ввиду авторы Хрома
Добавлю про Java и Green Threads.

Старые версии Linux не поддерживали Posix Threads, поэтому многопоточность реализовывалась банальным fork с запуском дочернего процесса. Для JVM это было прозрачно, но в системе болталась куча процессов, и запуск запуск треда занимал значительное время.

Обычная Sun JRE использует native threads. Однако в реализации под Solaris по желанию можно использовать библиотеку green threads самой ОС. В этом случае многопоточность реализуется по правилу m: n, то есть m native threads обслуживают по n green threads. Причем все это делается прозрачно для написанного кода. Некоторые другие имплементации JVM тоже поддерживают green threads (напр. JRockit).

Green threads уместно использовать в задачах с большим числом потоков. Классической задачей из книжки является тредовый сервер. На каждый установленный с клиентом коннекшн открывается новый тред, который обрабатывает запросы. Проблема в том, что при большом числе открытых потоков (>1000) планировщик задач ОС тратит основную часть времени только на бесполезное переключение между ними, несмотря на то, что сами потоки большую часть времени «спят» при чтении из сокета. Спасают green threads, где виртуальные потоки вешаются на один native thread.

Как работают green threads? Поскольку работает только один native thread, то в каждый момент времени может выполняться только один поток из виртуальных потоков. Переключение между потоками производится в момент, когда поток выполняет блокирующую операцию (синхронизация, I/O, sleep(), wait(), etc...). Более того, некоторые JVM искусственно вставляют в код потока операции переключения. В модели m: n после блокирующей операции виртуальный поток может быть продолжен другим m из имеющихся native потоков, поэтому выполнение всех потоков в этой модели происходит более-менее равномерно.

P.S. Более удачное решение для сервера в java является non-blocking I/O + thread pool
P.P.S. карма не позволяет писать статьи… :(
Зарегистрируйтесь на Хабре , чтобы оставить комментарий

Публикации

Истории