Как рабочие потоки работают в Nodejs?

Nodejs не может иметь встроенный API потоков, как это делают java и .net. Если потоки будут добавлены, природа самого языка изменится. Невозможно добавить потоки как новый набор доступных классов или функций.

В Nodejs 10.x добавлены рабочие потоки в качестве эксперимента, и теперь они стабильны с версии 12.x. Я просмотрел несколько блогов, но мало что понял, возможно, из-за недостатка знаний. Чем они отличаются от ниток.


person Sandeep Patel    schedule 16.12.2019    source источник


Ответы (1)


Рабочие потоки в Javascript несколько аналогичны WebWorkers в браузере. Они не имеют прямого доступа к каким-либо переменным с основным потоком или друг с другом, и единственный способ, которым они общаются с основным потоком, — это обмен сообщениями. Этот обмен сообщениями синхронизируется через цикл обработки событий. Это позволяет избежать всех классических условий гонки, когда несколько потоков пытаются получить доступ к одним и тем же переменным, потому что два отдельных потока не могут получить доступ к одним и тем же переменным в node.js. Каждый поток имеет свой собственный набор переменных, и единственный способ повлиять на переменные другого потока — отправить ему сообщение и попросить изменить его собственные переменные. Поскольку это сообщение синхронизируется через очередь событий этого потока, при доступе к переменным отсутствует риск классических условий гонки.

Потоки Java, с другой стороны, похожи на потоки C++ или собственные потоки в том, что они имеют доступ к одним и тем же переменным, а потоки свободно распределяются по времени, поэтому прямо в середине функции A, работающей в потоке A, выполнение может быть прервано, а функция B выполняется в потоке B. мог бежать. Поскольку оба могут свободно обращаться к одним и тем же переменным, возможны всевозможные условия состязания, если только кто-то вручную не использует инструменты синхронизации потоков (такие как мьютексы) для координации и защиты любого доступа к общим переменным. Этот тип программирования часто является источником очень трудно найти и практически невозможно надежно воспроизвести ошибки параллелизма. Несмотря на то, что он мощный и полезный для некоторых вещей системного уровня или более реального кода, любой, кроме очень опытного и опытного разработчика, может легко допустить дорогостоящие ошибки параллелизма. И очень сложно разработать тест, который скажет вам, действительно ли он стабилен при всех типах нагрузки или нет.

Node.js пытается избежать классических ошибок параллелизма, разделяя потоки в их собственное пространство переменных и заставляя всю связь между ними синхронизироваться через очередь событий. Это означает, что threadA/functionA никогда не прерывается произвольно, и какой-то другой код в вашем процессе изменяет некоторые общие переменные, к которым он обращался, пока не смотрел.

У node.js также есть поддержка, заключающаяся в том, что он может запускать дочерний_процесс, который может быть написан на любом языке и может использовать собственные потоки, если это необходимо, или можно фактически подключить собственный код и потоки реального системного уровня прямо в node.js с помощью дополнительного SDK. (и он взаимодействует с Javascript node.js через интерфейс SDK). И, по сути, ряд встроенных библиотек node.js делают именно это, чтобы показать функциональность, которая требует такого уровня доступа к среде nodejs. Например, реализация доступа к файлам использует пул собственных потоков для выполнения операций с файлами.


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

Таким образом, при использовании Workers в node.js все равно необходимо учитывать проблемы параллелизма при доступе к внешним ресурсам. node.js защищает локальную переменную среду для каждого работника, но ничего не может сделать с конкуренцией между внешними ресурсами. В этом отношении рабочие процессы node.js имеют те же проблемы, что и потоки Java, и программисту приходится кодировать для этого (эксклюзивный доступ к файлам, блокировки файлов, отдельные файлы для каждого рабочего процесса, использование базы данных для управления параллелизмом для хранения и т. д.). .).

person jfriend00    schedule 16.12.2019
comment
Рабочие потоки могут делиться памятью через SHARE_ENV, и в этом случае все ставки сняты :) - person Dave Newton; 16.12.2019
comment
@DaveNewton - SHARE_ENV предназначен только для переменных среды, а не для всех переменных Javascript, и да, тогда все ставки отключены для параллельного управления этими переменными среды. Существуют также способы отправки переменных из одного потока в другой в качестве средства передачи права собственности и доступа. - person jfriend00; 16.12.2019