javascript - used - void(0) trackid=sp-006
¿Se necesitan mutexes en javascript? (7)
Como señala @william,
Es posible que necesite un mutex si su código hace algo donde espera que no cambie un valor entre el momento en que se desencadenó el evento asíncrono y el momento en que se llamó a la devolución de llamada.
Esto se puede generalizar aún más: si su código hace algo donde espera el control exclusivo de un recurso hasta que se resuelva una solicitud asincrónica, es posible que necesite un mutex.
Un ejemplo simple es donde tienes 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 protegerlo de los usuarios de gatillo feliz haciendo clic fuera y, por lo tanto, creando múltiples registros. Hay una serie de enfoques para este problema (por ejemplo, desactivar el botón, habilitar el éxito de Ajax). También puedes usar un candado simple:
var save_lock = false;
$(''#save_button'').click(function(){
if(!save_lock){
//lock
save_lock=true;
$.ajax({
success:function()
//unlock
save_lock = false;
}
});
}
}
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 tengo conocimiento, es un mutex simple y es útil.
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 hilos en JS, ¿necesito usar mutexes en JS o no?
Específicamente, me pregunto acerca de los efectos del uso de funciones llamadas por setTimeout()
y XmlHttpRequest
''s onreadystatechange
en variables accesibles globalmente.
JavaScript tiene una sola hebra ... aunque Chrome puede ser una nueva bestia (creo que también tiene una sola hebra, pero cada pestaña tiene su propio hilo de JavaScript ... No lo he estudiado en detalle, así que no me cites ahí).
Sin embargo, una cosa de la que DEBE preocuparse es cómo su JavaScript manejará varias solicitudes ajax que regresen en el mismo orden en el que las envía. Entonces, todo lo que realmente debe preocuparse es asegurarse de que sus llamadas ajax se manejen de una manera que no se pisen los pies del otro si los resultados regresan en un orden diferente al que usted los envió.
Esto también es válido para los tiempos de espera ...
Cuando JavaScript crece multiprocesamiento, entonces tal vez se preocupe por mutexes y cosas por el estilo ....
JavaScript, el idioma , puede ser tan multiproceso como lo desee, pero las incrustaciones del navegador del motor de 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 cambios entre registrar y recibir una devolución de llamada no debe tomarse demasiado literal debido a esto, ya que no desearía bloquear la devolución de llamada intermedia, ya que la devolución de llamada que se desbloqueará se bloqueará detrás de la devolución de llamada actual ! (Guau, el inglés es una mierda para hablar de enhebrar). En este caso, probablemente desee hacer algo similar a volver a enviar el evento actual si se establece un indicador, ya sea literalmente o con el estilo de setTimeout ().
Si utiliza una incrustación diferente de JS y ejecuta múltiples subprocesos a la vez, puede ser un poco más arriesgado, pero debido a la forma en que JS puede utilizar devoluciones de llamadas tan fácilmente y bloquea los objetos en el acceso de 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 utilizaba múltiples subprocesos no proporcionara también algunas primitivas de bloqueo explícitas.
Perdón por el muro de texto!
Javascript se define como un lenguaje reentrante que significa que no hay subprocesos expuestos al usuario, puede haber subprocesos en la implementación. Las funciones como setTimeout()
y las devoluciones de llamada asincrónicas deben esperar a que el motor de script se setTimeout()
antes de que puedan ejecutarse.
Eso significa que todo lo que sucede en un evento debe finalizar antes de que se procese el siguiente evento.
Dicho esto, es posible que necesite un mutex si su código hace algo donde espera que no cambie un valor entre el momento en que se desencadenó 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 donde hace clic en un botón y envía un XmlHttpRequest que llama a una devolución de llamada cambia la estructura de datos de manera destructiva, y usted tiene otro botón que cambia la misma estructura de datos directamente, cuando el evento era disparado y cuando se ejecutó la devolución de llamada, el usuario podría haber hecho clic y actualizar la estructura de datos antes de la devolución de llamada, que luego podría perder el valor.
Si bien podrías crear una condición de carrera así, es muy fácil evitar eso en tu código ya que cada función será atómica. Sería mucho trabajo y tomaría algunos patrones de codificación extraños para crear la condición de carrera de hecho.
Las respuestas a esta pregunta están un poco desactualizadas, aunque son correctas en el momento en que se dieron. Y sigue siendo correcto si se mira una aplicación javascript del lado del cliente que NO utiliza webworkers.
Artículos sobre web-workers:
multithreading en javascript usando webworkers
Mozilla en webworkers
Esto muestra claramente que JavaScript a través de web-workers tiene capacidades de subprocesamiento múltiple. En cuanto a la pregunta, ¿se necesitan mutexes en javascript? No estoy seguro de esto. Pero esta publicación parece relevante:
Exclusión mutua para N subprocesos sincrónicos
Los eventos se señalan, pero la ejecución de JavaScript sigue siendo de un solo subproceso.
Según tengo entendido, cuando el evento se señaliza, 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 reasumido verá que estos cambios aparecen "de la nada".
Si desea "proteger" los datos compartidos, la bandera booleana simple debería ser suficiente.
Sí, se pueden requerir mutexes en Javascript cuando se accede 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:
function appendToList(item) {
var list = localStorage["myKey"];
if (list) {
list += "," + item;
}
else {
list = item;
}
localStorage["myKey"] = list;
}
Entre el momento en que el elemento localStorage es ''get'' y ''set'', otra pestaña podría haber modificado el valor. Por lo general, es poco probable, pero es posible. Debería juzgar usted mismo la probabilidad y el riesgo asociados con cualquier disputa en sus circunstancias particulares.
Vea los siguientes artículos para más detalles: