2012-04-04 9 views
6

Estoy usando this approach para almacenar datos en una matriz global que aloja un servidor http donde ciertas solicitudes manipularán la matriz global.¿Qué operaciones en el nodo son seguras para hilos?

Estoy un poco preocupado por problemas de enhebrado con ciertas operaciones, principalmente push y splice. Me imagino que si una solicitud me obliga a iterar sobre la matriz y eliminar elementos en función de un condicional, mientras que otra solicitud me llama al .push() en la matriz en la que me toparé con problemas. ¿Alguien puede confirmar esto?

Principalmente escribo en C# donde incluso un simple incremento no es seguro para subprocesos (al iniciar 25 hilos que hacen i ++, no garantizaré que i == 25 después de todo dicho y hecho).

actualización:

He escrito 5 ejemplos para demostrar lo que estoy hablando. Prueba 1 y Prueba 3 funcionan bien. La prueba 2 falla, debido a ... lo que normalmente se llamaría problemas de subprocesamiento (ya sean hilos de CPU reales o no). Las pruebas 4 y 5, cuando se ejecutan en paralelo, parecen funcionar (lo que significa que no tienen problemas de colisión como la Prueba 2).

http://pastebin.com/HcJHTDFY

estoy usando ApacheBench para poner a prueba, por lo que 1000 solicitudes paralelas.

Esto me lleva a pensar que la Prueba 1 y Prueba 3 trabajos bien porque nodejs no se ejecutarán más de 1 instancia de la app.get('/test3'...) de devolución de llamada en paralelo función javascript en paralelo (bloqueo?). Tan pronto como implemente setInterval/setTimeout, liberará nodejs para ejecutar otra instancia de la devolución de llamada (¿no bloqueo?).

Estoy tratando de entender qué diablos realmente significa non-blocking I/O model. ¿Significa que "hey es posible hacer no-bloqueo con setTimeout y setInterval si necesita no-bloqueo, de lo contrario vamos a bloquear cualquier otra función de nivel externo para que se ejecute hasta que agotemos la función en la que estamos" ? Siento que es imprescindible saber esto para no tener problemas pensando que podría implementar algo como/test2 y estar totalmente seguro.

Además, si intento no bloquear con mis devoluciones de llamada, ¿realmente debería llamar al setTimeout(code, 1)? ¿O hay un mejor camino?

Respuesta

10

Todos son seguros para subprocesos.

No hay subprocesos, JavaScript tiene un solo subproceso, es imposible que se ejecuten dos sentencias de JavaScript al mismo tiempo.

Dicho sea de paso, no se debe utilizar variables globales de todos modos porque globales son malas

Editar:

Prueba 2 falla porque usted está utilizando devoluciones de llamada asincrónicas, lo que significa que el control vuelve al nodo y puede manejar más solicitudes. Esto crea condiciones de carrera como se ve.

En nodo, todo lo que no sea bloques asincrónicos. Las únicas cosas asíncronas que tiene son setTimeout/setInterval/process.nextTick y cualquier operación IO asíncrona.

No se debe hacer manualmente un cálculo asíncrono.Uno debería simplemente evitar hacer demasiados cálculos.

He escrito un artículo sobre What it means to be non-blocking

+0

Entonces, cuando nodeJs/V8 entra en una función() {} que escribí, no se ejecutarán otras funciones mías, excepto las llamadas internas (como devoluciones de llamada)? – Langdon

+0

Por cierto, JavaScript puede ser de un solo subproceso, pero nodeJS parece ser de subprocesos múltiples, de lo contrario, las solicitudes posteriores al servidor http incorporado no podrían volver hasta que termine el primero. Además, http://stackoverflow.com/questions/7018093/nodejs-really-single-threaded – Langdon

+0

@ Langdon, ya sea que tenga varios hilos o no, es un detalle de implementación que no debería preocuparle. Todo lo que hace es IO asíncrono, ya sea directamente en el nivel del kernel o IO asíncrono emulado utilizando grupos de hilos – Raynos

-5

Raynos es sobre todo correcto. Pero el hecho de que JavaScript tenga una sola hebra no significa que puedas soltar tus defensas. Aún necesita estar al tanto de los hilos. Un buen ejemplo para ilustrar esto es cómo socket.io mantiene la conexión con clientes variados y aún puede hacer un seguimiento de estos clientes.

La parte de programación funcional de JavaScript funciona mediante enlace variable (como ... MUCHO). El hecho de no estar al tanto de los hilos te hace asumir falsamente que tus variables están correctamente enlazadas. Al igual que el ejemplo de socket.io, ¿cómo puede estar seguro de que la conexión que está recibiendo es del cliente que cree que está obteniendo? ¿Qué pasa si el enlace de referencia salió mal y la conexión realmente hace referencia a un cliente diferente?

Este es el tipo de cosas que debe tener cuidado.

+1

JavaScript no tiene pase por referencia. Eso y las tonterías de las que hablas no tienen nada que ver con los hilos. node.js ni siquiera usa subprocesos si el sistema operativo admite Async IO en el nivel de kernel – Raynos

+0

@lightblade Haters ... – Langdon

+1

Para dar realimentación/crítica. ¿Cuándo "el enlace de referencia saldrá mal"? Cuándo la conexión haría referencia a un "cliente" diferente. Sí, hay trampas de simultaneidad que debe tener en cuenta, pero no las describe y no están relacionadas con los hilos – Raynos

Cuestiones relacionadas