ventajas que funciona español ejemplos desventajas definicion como caracteristicas javascript concurrency

funciona - ¿Se garantiza que JavaScript sea de un solo hilo?



javascript que es (12)

Se sabe que JavaScript es de un solo hilo en todas las implementaciones de navegadores modernos, pero ¿está especificado en algún estándar o es simplemente por tradición? ¿Es totalmente seguro asumir que JavaScript siempre es de un solo hilo?


@Bobince está proporcionando una respuesta realmente opaca.

Riffing de la respuesta de Már Örlygsson, Javascript siempre es de un solo hilo debido a este simple hecho: todo en Javascript se ejecuta a lo largo de una sola línea de tiempo.

Esa es la definición estricta de un lenguaje de programación de un solo hilo.


Buena pregunta. Me encantaría decir "sí". No puedo

Por lo general, se considera que JavaScript tiene un solo hilo de ejecución visible para los scripts (*), de modo que cuando se ingresa su secuencia de comandos en línea, el detector de eventos o el tiempo de espera, usted permanece completamente en control hasta que regrese del final de su bloqueo o función.

(*: ignorar la pregunta de si los navegadores realmente implementan sus motores JS utilizando un subproceso del sistema operativo, o si los trabajadores web introducen otros subprocesos limitados).

Sin embargo, en realidad esto no es del todo cierto , en formas desagradables astutas.

El caso más común son los eventos inmediatos. Los navegadores los activarán de inmediato cuando su código haga algo para provocarlos:

var l= document.getElementById(''log''); var i= document.getElementById(''inp''); i.onblur= function() { l.value+= ''blur/n''; }; setTimeout(function() { l.value+= ''log in/n''; l.focus(); l.value+= ''log out/n''; }, 100); i.focus();

<textarea id="log" rows="20" cols="40"></textarea> <input id="inp">

Resultados en log in, blur, log out en todos excepto IE. Estos eventos no solo se activan porque llamaste a focus() directamente, podrían suceder porque llamaste a alert() , o abriste una ventana emergente, o cualquier otra cosa que mueva el foco.

Esto también puede resultar en otros eventos. Por ejemplo, agregue un i.onchange escucha i.onchange y escriba algo en la entrada antes de que la llamada focus() lo log in, change, blur, log out y el orden de log in, change, blur, log out es log in, change, blur, log out , excepto en Opera, donde es log in, blur, log out, change e IE donde es (incluso menos explicable) log in, change, log out, blur .

De manera similar, al click() en un elemento que proporciona, llama al controlador onclick inmediatamente en todos los navegadores (¡al menos esto es consistente!).

(Estoy usando las propiedades directas on... controlador de eventos aquí, pero lo mismo sucede con addEventListener y attachEvent ).

También hay un montón de circunstancias en las que los eventos pueden activarse mientras se enlaza tu código, a pesar de que no has hecho nada para provocarlo. Un ejemplo:

var l= document.getElementById(''log''); document.getElementById(''act'').onclick= function() { l.value+= ''alert in/n''; alert(''alert!''); l.value+= ''alert out/n''; }; window.onresize= function() { l.value+= ''resize/n''; };

<textarea id="log" rows="20" cols="40"></textarea> <button id="act">alert</button>

Pulsa alert y obtendrás un cuadro de diálogo modal. No más secuencias de comandos ejecutadas hasta que desestime ese diálogo, ¿sí? No Cambia el tamaño de la ventana principal y obtendrás alert in, resize, alert out en el área de texto.

Podría pensar que es imposible cambiar el tamaño de una ventana mientras que un cuadro de diálogo modal está activo, pero no tanto: en Linux, puede cambiar el tamaño de la ventana todo lo que quiera; en Windows no es tan fácil, pero puede hacerlo cambiando la resolución de la pantalla de una más grande a una más pequeña en la que la ventana no se ajusta, lo que hace que se redimensione.

Podría pensar, bueno, solo el cambio de resize (y probablemente algunos más como scroll ) puede dispararse cuando el usuario no tiene una interacción activa con el navegador porque la secuencia de comandos está enlazada. Y para ventanas individuales puede que tengas razón. Pero todo eso va a funcionar tan pronto como estás ejecutando scripts entre ventanas. Para todos los navegadores que no sean Safari, que bloquea todas las ventanas / pestañas / marcos cuando alguno de ellos está ocupado, puede interactuar con un documento desde el código de otro documento, ejecutándose en un hilo de ejecución separado y haciendo que los controladores de eventos relacionados fuego.

Los lugares donde los eventos que puede generar se pueden generar mientras la secuencia de comandos aún se está enlazando:

  • cuando las ventanas emergentes modales ( alert , confirm , prompt ) están abiertas, en todos los navegadores excepto en Opera;

  • durante showModalDialog en los navegadores que lo admiten;

  • el cuadro de diálogo “Un script en esta página puede estar ocupado ...”, incluso si elige dejar que el script continúe ejecutándose, permite que eventos como el cambio de tamaño y el desenfoque se activen y se manejen incluso cuando el script está en medio de un ajetreo, excepto en Opera.

  • hace un tiempo para mí, en IE con Sun Java Plugin, llamar a cualquier método en un applet podría permitir que los eventos se activen y que se vuelvan a ingresar los scripts. Esto siempre fue un error sensible al tiempo, y es posible que Sun lo haya solucionado (ciertamente lo espero).

  • probablemente más Ha pasado un tiempo desde que probé esto y los navegadores han ganado complejidad desde entonces.

En resumen, la mayor parte del tiempo, la mayoría de las veces, parece que JavaScript tiene un subproceso único de ejecución controlado por eventos. En realidad, no tiene tal cosa. No está claro qué parte de esto es simplemente un error y cuánto diseño deliberado, pero si está escribiendo aplicaciones complejas, especialmente en ventanas cruzadas / scripts de marcos, hay muchas posibilidades de que pueda morderlo, y en forma intermitente, Formas difíciles de depurar.

Si lo peor es lo peor, puede resolver los problemas de concurrencia dirigiendo todas las respuestas a los eventos. Cuando llega un evento, colóquelo en una cola y trate la cola en orden más adelante, en una función setInterval . Si está escribiendo un marco que pretende ser usado por aplicaciones complejas, esto podría ser un buen paso. postMessage que postMessage también postMessage el dolor de los scripts entre documentos en el futuro.


Bueno, Chrome es multiproceso, y creo que cada proceso trata con su propio código Javascript, pero por lo que el código sabe, es de "un solo hilo".

No hay soporte alguno en Javascript para subprocesos múltiples, al menos no explícitamente, por lo que no hace una diferencia.


Diría que la especificación no impide que alguien cree un motor que ejecute javascript en varios subprocesos, lo que requiere que el código realice la sincronización para acceder al estado de objeto compartido.

Creo que el paradigma de no bloqueo de subproceso único surgió de la necesidad de ejecutar javascript en navegadores en los que la interfaz de usuario nunca debería bloquearse.

Nodejs ha seguido el enfoque de los navegadores.

El motor Rhino , sin embargo, soporta ejecutar código js en diferentes hilos . Las ejecuciones no pueden compartir el contexto, pero pueden compartir el alcance. Para este caso específico la documentación establece:

... "Rhino garantiza que los accesos a las propiedades de los objetos JavaScript son atómicos en todos los subprocesos, pero no ofrece más garantías para que los scripts se ejecuten en el mismo ámbito al mismo tiempo. Si dos scripts usan el mismo ámbito simultáneamente, los scripts son Responsable de coordinar cualquier acceso a variables compartidas ".

Al leer la documentación de Rhino, llego a la conclusión de que puede ser posible que alguien escriba una api de javascript que también genere nuevos subprocesos de javascript, pero la api sería específica del rinoceronte (por ejemplo, el nodo solo puede generar un nuevo proceso).

Me imagino que incluso para un motor que admita múltiples subprocesos en javascript debería haber compatibilidad con scripts que no consideren multiproceso o bloqueo.

Concearning los navegadores y los nodos de la manera que lo veo es:

  • ¿Se ejecuta todo el código js en un solo hilo? : Si

  • ¿Puede el código js hacer que otros hilos se ejecuten? : Si

  • ¿Pueden estos hilos cambiar el contexto de ejecución de js ?: No. Pero pueden (directamente / indirectamente (?)) Agregarse a la cola de eventos.

Por lo tanto, en el caso de los navegadores y los nodejs (y probablemente muchos otros motores), javascript no es multiproceso, pero sí los motores.


En realidad, una ventana principal puede comunicarse con ventanas o marcos hijos o hermanos que tienen sus propios hilos de ejecución en ejecución.


He intentado el ejemplo de @ bobince con una ligera modificación:

<html> <head> <title>Test</title> </head> <body> <textarea id="log" rows="20" cols="40"></textarea> <br /> <button id="act">Run</button> <script type="text/javascript"> let l= document.getElementById(''log''); let b = document.getElementById(''act''); let s = 0; b.addEventListener(''click'', function() { l.value += ''click begin/n''; s = 10; let s2 = s; alert(''alert!''); s = s + s2; l.value += ''click end/n''; l.value += `result = ${s}, should be ${s2 + s2}/n`; l.value += ''----------/n''; }); window.addEventListener(''resize'', function() { if (s === 10) { s = 5; } l.value+= ''resize/n''; }); </script> </body> </html>

Entonces, cuando presionas Ejecutar, cierra la ventana emergente de alerta y haces un "hilo único", deberías ver algo como esto:

click begin click end result = 20, should be 20

Pero si intenta ejecutar esto en Opera o Firefox estable en Windows y minimizar / maximizar la ventana con una ventana emergente de alerta en la pantalla, entonces habrá algo como esto:

click begin resize click end result = 15, should be 20

No quiero decir que esto es "multihilo", pero una parte del código se ejecutó en un momento equivocado, no esperaba esto, y ahora tengo un estado dañado. Y mejor saber sobre este comportamiento.


Intente anidar dos funciones setTimeout una dentro de la otra y se comportarán de forma múltiple (es decir, el temporizador externo no esperará a que se complete el interno antes de ejecutar su función).


JavaScript / ECMAScript está diseñado para vivir dentro de un entorno host. Es decir, JavaScript no hace nada a menos que el entorno del host decida analizar y ejecutar un script determinado, y proporcionar objetos de entorno que permitan que JavaScript sea realmente útil (como el DOM en los navegadores).

Creo que una determinada función o bloque de script se ejecutará línea por línea y eso está garantizado para JavaScript. Sin embargo, tal vez un entorno host pueda ejecutar múltiples scripts al mismo tiempo. O bien, un entorno de host siempre puede proporcionar un objeto que proporciona subprocesos múltiples. setTimeout y setInterval son ejemplos, o al menos pseudo-ejemplos, de un entorno host que proporciona una forma de realizar alguna concurrencia (incluso si no es exactamente concurrencia).


No.

Voy contra la multitud aquí, pero tengan paciencia conmigo. Se pretende que un solo script JS sea un solo hilo, pero esto no significa que no pueda interpretarse de manera diferente.

Digamos que tienes el siguiente código ...

var list = []; for (var i = 0; i < 10000; i++) { list[i] = i * i; }

Esto se escribe con la expectativa de que al final del bucle, la lista debe tener 10000 entradas, que son el índice al cuadrado, pero la VM podría notar que cada iteración del bucle no afecta al otro, y reinterpretar usando dos subprocesos.

Primer hilo

for (var i = 0; i < 5000; i++) { list[i] = i * i; }

Segundo hilo

for (var i = 5000; i < 10000; i++) { list[i] = i * i; }

Estoy simplificando aquí, porque los arreglos JS son más complicados que los trozos de memoria, pero si estos dos scripts pueden agregar entradas al arreglo de una manera segura para subprocesos, entonces, cuando ambos hayan terminado de ejecutarse, tendrán que El mismo resultado que la versión de un solo hilo.

Si bien no estoy al tanto de que una VM detecte un código paralelizable como este, parece probable que pueda surgir en el futuro para las máquinas virtuales de JIT, ya que podría ofrecer más velocidad en algunas situaciones.

Tomando este concepto aún más, es posible que el código pueda ser anotado para que la máquina virtual sepa qué convertir a código de múltiples subprocesos.

// like "use strict" this enables certain features on compatible VMs. "use parallel"; var list = []; // This string, which has no effect on incompatible VMs, enables threading on // this loop. "parallel for"; for (var i = 0; i < 10000; i++) { list[i] = i * i; }

Dado que los Trabajadores Web están llegando a Javascript, es poco probable que este ... sistema más feo llegue a existir, pero creo que es seguro decir que Javascript es de un solo hilo por tradición.


Sí, aunque Internet Explorer 9 compilará su Javascript en un hilo separado como preparación para la ejecución en el hilo principal. Sin embargo, esto no cambia nada para usted como programador.


Sí, aunque todavía puede sufrir algunos de los problemas de la programación concurrente (principalmente condiciones de carrera) al usar cualquiera de las API asíncronas, como las devoluciones de llamada setInterval y xmlhttp.


Yo diría que sí, porque prácticamente todo el código javascript existente (al menos no trivial) se rompería si el motor javascript de un navegador lo ejecutara de forma asíncrona.

Agregue a eso el hecho de que HTML5 ya especifica Web Workers (una API estandarizada y explícita para el código javascript de subprocesos múltiples) la introducción de subprocesos múltiples en el Javascript básico sería en gran medida inútil.

( Nota para otros comentaristas: a pesar de que los setTimeout/setInterval , HTTP-request onload (XHR) y los eventos de IU (clic, enfoque, etc.) brindan una impresión general de multihilo: aún se ejecutan en una sola línea de tiempo - uno a la vez - así que incluso si no conocemos de antemano su orden de ejecución, no hay que preocuparse por el cambio de condiciones externas durante la ejecución de un controlador de eventos, una función temporizada o una devolución de llamada XHR.