Я видел эту ссылку: Реализация взаимного исключения в JavaScript . С другой стороны, я читал, что в javascript нет потоков, но что именно это означает?
Когда происходят события, где в коде они могут прерываться?
А если в JS нет потоков, нужно ли использовать в JS мьютексы или нет?
В частности, меня интересуют эффекты использования функций, вызываемых setTimeout()
и XmlHttpRequest
для onreadystatechange
глобально доступных переменных.
Ответы:
Javascript определяется как реентерабельный язык, что означает отсутствие потоковой передачи, доступной пользователю, в реализации могут быть потоки. Такие функции, как
setTimeout()
асинхронные обратные вызовы, должны дождаться, пока обработчик сценариев спит, прежде чем они смогут работать.Это означает, что все, что происходит в событии, должно быть завершено до того, как будет обработано следующее событие.
При этом вам может понадобиться мьютекс, если ваш код делает что-то там, где он ожидает, что значение не изменится между моментом запуска асинхронного события и моментом вызова обратного вызова.
Например, если у вас есть структура данных, в которой вы нажимаете одну кнопку, и она отправляет XmlHttpRequest, который вызывает обратный вызов, деструктивным образом изменяет структуру данных, и у вас есть другая кнопка, которая напрямую изменяет ту же структуру данных, между тем, когда событие было сработал, и когда был выполнен обратный вызов, пользователь мог щелкнуть и обновить структуру данных перед обратным вызовом, что затем могло бы потерять значение.
Хотя вы можете создать такое состояние гонки, очень легко предотвратить это в своем коде, поскольку каждая функция будет атомарной. Для фактического создания состояния гонки потребовалось бы много работы и несколько странных шаблонов кодирования.
источник
Ответы на этот вопрос немного устарели, но верны в то время, когда они были даны. И все же правильно, если смотреть на клиентское приложение javascript, которое НЕ использует веб-работников.
Статьи о веб-
воркерах : многопоточность в javascript с использованием веб- воркеров
Mozilla для веб-воркеров
Это ясно показывает, что javascript через веб-воркеров имеет возможности многопоточности. Что касается вопроса, нужны ли мьютексы в javascript? Я не уверен в этом. Но этот пост stackoverflow кажется актуальным:
Взаимное исключение для N асинхронных потоков
источник
Как отмечает @william,
Это можно обобщить и дальше - если ваш код делает что-то там, где он ожидает монопольного контроля над ресурсом до тех пор, пока асинхронный запрос не разрешится, вам может понадобиться мьютекс.
Простой пример: у вас есть кнопка, которая запускает вызов ajax для создания записи в серверной части. Вам может потребоваться немного кода, чтобы защитить вас от того, чтобы довольные пользователи щелкали мышью и создавали несколько записей. Есть несколько подходов к этой проблеме (например, отключение кнопки, включение при успешном использовании ajax). Вы также можете использовать простую блокировку:
Я не уверен, что это лучший подход, и мне было бы интересно посмотреть, как другие обрабатывают взаимное исключение в javascript, но насколько мне известно, это простой мьютекс, и он удобен.
источник
while
сsetTimeout
илиsetInterval
сclearInterval
после n сбоев, чтобы у вас была логика повторных попыток и тайм-аута. Если оставить как есть, вы просто обойдете заблокированный код. Внешняя обработка мьютексов и общих объектов так же важна, как и сами реализации.JavaScript однопоточный ... хотя Chrome может быть новым зверем (я думаю, что он тоже однопоточный, но у каждой вкладки есть собственный поток JavaScript ... Я не рассматривал его подробно, поэтому не цитируйте меня там).
Однако вам НЕОБХОДИМО беспокоиться о том, как ваш JavaScript будет обрабатывать несколько запросов ajax, возвращающихся не в том же порядке, в котором вы их отправляете. Итак, все, о чем вам действительно нужно беспокоиться, - это убедиться, что ваши вызовы ajax обрабатываются таким образом, чтобы они не наступали друг другу на ноги, если результаты вернутся в другом порядке, чем вы их отправили.
Это касается и таймаутов ...
Когда JavaScript становится многопоточным, можно беспокоиться о мьютексах и тому подобном ...
источник
Да, мьютексы могут потребоваться в Javascript при доступе к ресурсам, которые используются совместно вкладками / окнами, например localStorage .
Например, если у пользователя открыты две вкладки, простой код, подобный следующему, небезопасен:
Между моментом, когда элемент localStorage был «получен» и «установлен», другая вкладка могла изменить значение. Как правило, это маловероятно, но возможно - вам нужно будет самостоятельно судить о вероятности и риске, связанных с любым конфликтом в ваших конкретных обстоятельствах.
См. Следующие статьи для получения более подробной информации:
источник
Язык JavaScript может быть сколь угодно многопоточным, но при встраивании в браузер движка javascript выполняется только один обратный вызов (onload, onfocus, <script> и т. Д.) За раз (предположительно для каждой вкладки). Предложение Уильяма об использовании Mutex для изменений между регистрацией и получением обратного вызова не следует воспринимать слишком буквально из-за этого, поскольку вы не захотите блокировать промежуточный обратный вызов, поскольку обратный вызов, который его разблокирует, будет заблокирован за текущим обратным вызовом ! (Вау, английский отстой, если говорить о потоковой передаче.) В этом случае вы, вероятно, захотите сделать что-то вроде повторной отправки текущего события, если установлен флаг, буквально или с помощью setTimeout ().
Если вы используете другое встраивание JS и одновременно выполняет несколько потоков, это может стать немного более рискованным, но из-за того, как JS может так легко использовать обратные вызовы и блокировать объекты при доступе к свойствам, явная блокировка не так необходима . Однако я был бы удивлен, если бы встраивание, разработанное для общего кода (например, сценариев игры), в котором использовалась многопоточность, также не давало некоторых явных примитивов блокировки.
Простите за стену текста!
источник
События сигнализируются, но выполнение JavaScript по-прежнему однопоточное.
Я понимаю, что при получении сигнала о событии движок останавливает то, что он выполняет в данный момент, чтобы запустить обработчик событий. После завершения обработчика выполнение скрипта возобновляется. Если обработчик событий изменил некоторые общие переменные, тогда возобновленный код увидит, что эти изменения появляются «неожиданно».
Если вы хотите «защитить» общие данные, достаточно простого логического флага.
источник