He visto este enlace: Implementación de la exclusión mutua en JavaScript . Por otro lado, he leído que no hay hilos en javascript, pero ¿qué significa eso exactamente?
Cuando ocurren eventos, ¿en qué parte del código pueden interrumpir?
Y si no hay subprocesos en JS, ¿necesito usar mutex en JS o no?
En concreto, me pregunto acerca de los efectos del uso de las funciones llamadas por setTimeout()
y XmlHttpRequest
's onreadystatechange
en variables globalmente accesibles.
javascript
multithreading
mutex
Ovesh
fuente
fuente
Respuestas:
Javascript se define como un lenguaje reentrante , lo que significa que no hay subprocesos expuestos al usuario, puede haber subprocesos en la implementación. Las funciones como
setTimeout()
las devoluciones de llamada asincrónicas deben esperar a que el motor de secuencia de comandos se suspenda antes de poder ejecutarse.Eso significa que todo lo que sucede en un evento debe terminarse antes de que se procese el próximo evento.
Dicho esto, es posible que necesite un mutex si su código hace algo en el que espera que un valor no cambie entre el momento en que se disparó el evento asíncrono y el momento en que se llamó a la devolución de llamada.
Por ejemplo, si tiene una estructura de datos en la que hace clic en un botón y envía una XmlHttpRequest que llama a una devolución de llamada, cambia la estructura de datos de una manera destructiva, y tiene otro botón que cambia la misma estructura de datos directamente, entre el momento en que se produjo el evento. se disparó y cuando se ejecutó la devolución de llamada, el usuario pudo haber hecho clic y actualizado la estructura de datos antes de la devolución de llamada, lo que podría perder el valor.
Si bien puede crear una condición de carrera como esa, es muy fácil evitarlo en su código, ya que cada función será atómica. Sería mucho trabajo y se necesitarían algunos patrones de codificación extraños para crear la condición de carrera de hecho.
fuente
Las respuestas a esta pregunta están un poco desactualizadas, aunque son correctas en el momento en que se dieron. Y aún así es correcto si mira una aplicación de JavaScript del lado del cliente que NO usa webworkers.
Artículos sobre trabajadores web:
multiproceso en javascript usando webworkers
Mozilla en webworkers
Esto muestra claramente que javascript a través de web-workers tiene capacidades de subprocesos múltiples. En cuanto a la pregunta, ¿se necesitan mutex en javascript? No estoy seguro de esto. Pero esta publicación de stackoverflow parece relevante:
Exclusión mutua para N subprocesos asincrónicos
fuente
Como señala @william,
Esto se puede generalizar aún más: si su código hace algo en lo que espera el control exclusivo de un recurso hasta que se resuelve una solicitud asincrónica, es posible que necesite un mutex.
Un ejemplo simple es donde tiene un botón que dispara una llamada ajax para crear un registro en el back-end. Es posible que necesite un poco de código para evitar que los usuarios felices hagan clic y creen múltiples registros. Hay una serie de enfoques para este problema (por ejemplo, deshabilitar el botón, habilitar en caso de éxito de ajax). También puede usar un candado simple:
No estoy seguro de si ese es el mejor enfoque y me interesaría ver cómo otros manejan la exclusión mutua en javascript, pero hasta donde sé, es un simple mutex y es útil.
fuente
while
consetTimeout
osetInterval
conclearInterval
después de n fallas para que tenga una lógica de reintento y tiempo de espera. Dejarlo como está significa que simplemente omitiría el código que está bloqueado. El manejo externo con mutex y objetos compartidos es tan importante como las implementaciones mismas.JavaScript es de un solo subproceso ... aunque Chrome puede ser una nueva bestia (creo que también es de un solo subproceso, pero cada pestaña tiene su propio hilo de JavaScript ... No lo he analizado en detalle, así que no me cites ahí).
Sin embargo, una cosa de la que DEBE preocuparse es cómo su JavaScript manejará múltiples solicitudes ajax que regresan en el mismo orden en que las envía. Por lo tanto, todo lo que realmente debe preocuparse es asegurarse de que sus llamadas ajax se manejen de una manera que no se pisoteen si los resultados regresan en un orden diferente al que los envió.
Esto también se aplica a los tiempos de espera ...
Cuando JavaScript crece con múltiples subprocesos, entonces tal vez se preocupe por las exclusiones mutuas y similares ...
fuente
Sí, se pueden requerir exclusiones mutuas en Javascript al acceder a recursos que se comparten entre pestañas / ventanas, como localStorage .
Por ejemplo, si un usuario tiene dos pestañas abiertas, un código simple como el siguiente no es seguro:
Entre el momento en que el elemento localStorage se 'obtiene' y 'establece', otra pestaña podría haber modificado el valor. Por lo general, es poco probable, pero es posible: deberá juzgar por sí mismo la probabilidad y el riesgo asociados con cualquier disputa en sus circunstancias particulares.
Consulte los siguientes artículos para obtener más detalles:
fuente
JavaScript, el lenguaje , puede ser tan multiproceso como desee, pero las incrustaciones del navegador del motor javascript solo ejecutan una devolución de llamada (onload, onfocus, <script>, etc.) a la vez (por pestaña, presumiblemente). La sugerencia de William de usar un mutex para los cambios entre el registro y la recepción de una devolución de llamada no debe tomarse demasiado literalmente debido a esto, ya que no querrá bloquear la devolución de llamada intermedia ya que la devolución de llamada que lo desbloqueará se bloqueará detrás de la devolución de llamada actual. ! (Vaya, el inglés apesta para hablar de subprocesos.) En este caso, probablemente quieras hacer algo en la línea de volver a enviar el evento actual si se establece una bandera, ya sea literalmente o con cosas como setTimeout ().
Si está utilizando una incrustación diferente de JS, y eso ejecuta varios subprocesos a la vez, puede ser un poco más arriesgado, pero debido a la forma en que JS puede usar devoluciones de llamada tan fácilmente y bloquea objetos en el acceso a la propiedad, el bloqueo explícito no es tan necesario . Sin embargo, me sorprendería que una incrustación diseñada para código general (p. Ej., Secuencias de comandos de juegos) que usara múltiples subprocesos no proporcionara también algunas primitivas de bloqueo explícitas.
¡Perdón por la pared de texto!
fuente
Los eventos se señalan, pero la ejecución de JavaScript sigue siendo de un solo subproceso.
Tengo entendido que cuando se indica un evento, el motor detiene lo que está ejecutando en ese momento para ejecutar el controlador de eventos. Una vez finalizado el controlador, se reanuda la ejecución del script. Si el controlador de eventos cambió algunas variables compartidas, el código reanudado verá estos cambios aparecer "de la nada".
Si desea "proteger" los datos compartidos, una simple bandera booleana debería ser suficiente.
fuente