Рабочие потоки в 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