2010-06-21 6 views
18

estaba leyendo cómo Clojure es 'cool' debido a su sintaxis + se ejecuta en la JVM por lo que es multiproceso, etc, etcConfundido, ¿hay idiomas como python, ruby ​​single threaded? a diferencia de decir java? (Para aplicaciones web)

son lenguajes como Ruby y Python sola rosca en la naturaleza, entonces? (cuando se ejecuta como una aplicación web).

¿Cuáles son las diferencias subyacentes entre python/ruby ​​y decir que java se ejecuta en tomcat?

¿El servidor web no tiene un conjunto de hilos para trabajar en todos los casos?

+3

Dónde leíste esto? [Cita requerida] – Kris

+0

@ircmaxell, (por lo que su valor :) que usted debe fijar esto como una respuesta junto con una citación – chiccodoro

+0

siento que es más bien, 'infraestructura sólida para la programación multiproceso' mercados clojure así que (erróneamente) asumiendo otros marcos son no multihilo. – Blankman

Respuesta

22

Tanto Python como Ruby son totalmente compatibles con multi-threading. Hay algunas implementaciones (por ejemplo, CPython, MRI, YARV) que no pueden ejecutar subprocesos en paralelo, pero eso es una limitación de esas implementaciones específicas, no del lenguaje. Esto es similar a Java, donde también hay algunas implementaciones que no pueden ejecutar subprocesos en paralelo, pero eso no significa que Java tenga un solo subproceso.

Nótese que en ambos casos hay un montón de implementaciones, que puede hilos en paralelos: PyPy, IronPython, Jython, IronRuby y JRuby son solamente algunos de los ejemplos.

La principal diferencia entre Clojure por un lado y Python, Ruby, Java, C#, C++, C, PHP y casi todos los demás mainstream y el lenguaje no tan dominante en el otro lado es que Clojure tiene un sane modelo de concurrencia. Todos los demás lenguajes utilizan subprocesos, que hemos conocido como un modelo de mala concurrencia durante al menos 40 años. Clojure OTOH tiene un modelo de actualización que le permite no solo presentar al programador uno, sino múltiples modelos de simultaneidad: actualizaciones atómicas, memoria transaccional de software, agentes asíncronos, variables globales localizadas por thread de concordancia, futuros, promesas, concurrencia de flujo de datos y en el futuro posiblemente aún más.

+0

+1 Entonces, ¿las implementaciones * "predeterminadas" * de Python y Ruby (usted sabe ésas donde participan Guido y Matz) * single threaded *? – OscarRyz

+0

No puedo hablar por Python, pero en cuanto a Ruby, no existe una "implementación predeterminada".Hay una especificación de idioma y hay un grupo de compiladores y/o intérpretes que implementan esa especificación de idioma. Cada compilador o intérprete que implementa fielmente la especificación es una implementación de Ruby y ninguno de ellos es de alguna manera especial o "predeterminado" o lo que sea. –

+3

Técnicamente, las implementaciones de stock "tienen múltiples subprocesos". Pero debido al bloqueo de Intérprete global, solo se puede ejecutar un hilo a la vez. Entonces, en esencia ... no, no tienen múltiples subprocesos. Esto se aplica tanto a Ruby como a Python. –

3

Ciertamente, el servidor web tendrá un conjunto de hilos. Eso solo está fuera del control de tu programa. Esos hilos se usan para manejar solicitudes HTTP. Cada solicitud HTTP se maneja en un subproceso separado y el subproceso se devuelve al grupo cuando finaliza la respuesta HTTP asociada. Si el servidor web no tiene ese grupo, hubiera sido extremadamente lento en la prestación.

Si un lenguaje de programación es singlethreaded o multiproceso depende de la posibilidad de generar programáticamente hilos nuevos utilizando el idioma en cuestión. Si eso no es posible, entonces el lenguaje es singlethreaded, por ejemplo PHP. Por lo que puedo ver, tanto Ruby como Python admiten multihilo.

+0

Como una pregunta relacionada/más específica: ¿una persona nueva en Ruby/Rails necesita hacer algo elegante al implementar una aplicación web o una secuencia de comandos CGI para obtener esa funcionalidad de grupo de servidores web? es decir, si tuviera que copiar mis archivos .rb a un servidor web, ¿podría el servidor web servir múltiples solicitudes concurrentes usando el mismo código, o se necesita alguna configuración elegante? – LoveMeSomeCode

+0

Bueno, generalmente hay un poco más para implementar una aplicación Ruby que simplemente copiar archivos y señalar el servidor web hacia ellos, pero sí, el servidor maneja engendrar nuevos hilos (o procesos) por sí mismo. –

4

La mayoría de los lenguajes no definen sola o multihebra. Por lo general, eso queda en manos de las bibliotecas para implementarlo.

Dicho esto, algunos idiomas son mejores que otros. CPython, por ejemplo, tiene problemas con el bloqueo de intérpretes durante el subprocesamiento múltiple, Jython (Python ejecutándose en la JVM) no lo hace.

Parte de la potencia real de Clojure (IMO) es que se ejecuta en la JVM. Obtiene multiprocesamiento y toneladas de bibliotecas de forma gratuita.

+0

¿por qué cerrar sobre java? su breve sintaxis? – Blankman

+4

@Blankman: ¿por qué * cualquier * idioma sobre cualquier otro? Hay muchas, ** muchas ** razones por las cuales uno puede elegir Clojure sobre Java o viceversa; Basta decir que una respuesta de una línea en un comentario sería insuficiente para abordar la pregunta. El argumento de ablerman era simplemente que Clojure puede aprovechar una de las principales ventajas de Java, además de ofrecer la suya propia. –

+0

+1 a Andrzej comentario. También diría que para mí, la sintaxis es lo que me atrajo a Clojure lejos de Python y C#. Y esto viene de un tipo que encuentra a Java espantoso. A cada uno lo suyo. –

0

Rubí

The Ruby intérprete es roscado único, es decir, que varios de sus métodos no es seguro para subprocesos.

En el mundo de los rieles, este hilo único se ha enviado principalmente al servidor. Por lo tanto, verá que nginx se está ejecutando con un grupo de servidores mongrel, cada uno de los cuales tiene un intérprete en la memoria, procesa 1 solicitud a la vez y en su propio hilo.

Pasajero, corriendo "ruby enterprise" trae el concepto de recolección de basura y algo de seguridad de hilos en Rails, y es agradable.

Todavía hay trabajo por hacer en Rails en esta área, pero está llegando lentamente, pero en general, la idea es tener múltiples servicios y servidores.

+2

"The Ruby Interpreter is single threaded": Wrong. En primer lugar, no existe el "intérprete Ruby". Hay alrededor de una docena de ellos, y todos menos uno tienen múltiples hilos. "Passenger, ejecutar Ruby Enterprise Edition trae el concepto de recolección de basura": Incorrecto. * Todas * Ruby Implementations tienen recolección de basura y * siempre * han tenido recolección de basura desde la primera versión hace 17 años. Además, REE no tiene nada que ver con la seguridad de hilos. Y no "trae nada a Rails", de hecho, no tiene nada que ver con Rails, es solo una implementación de Ruby ... –

+0

... como cualquier otra. (De hecho, ni siquiera es una implementación de Ruby, es solo un pequeño conjunto de parches para MRI). –

+0

Tiene razón en cuanto a la recolección de basura, mala elección de palabras; Quise decir que permite que las conexiones y otros objetos de memoria se reutilicen en "pasajeros", lo que da como resultado una menor huella de memoria y un mayor conteo de simultaneidad. YMMV, pero en mi experiencia, es algo bueno. –

0

Cómo desenredar los nudos en al esos hilos ...

Clojure no inventó roscado, sin embargo, tiene particularmente fuerte apoyo a la misma con el software transaccional memoria, Átomos, agentes, operaciones de correlación paralelos, ...

Todos los demás han acumulado soporte de enhebrado. Ruby es un caso especial, ya que tiene hilos verdes en algunas implementaciones que son un tipo de subprocesos de software emulado y no usan todos los núcleos. 1.9 pondrá esto a descansar.

En cuanto a los servidores web, no siempre funcionan en multiproceso, apache se ha ejecutado tradicionalmente como una bandada de daemons que son un conjunto de procesos de un único subproceso. Ahora, actualmente, hay más opciones para ejecutar servidores apache.

Para resumir todos los idiomas modernos, admite el enhebrado de una forma u otra.

Los lenguajes más nuevos como scala y clojure están agregando soporte específico para mejorar el trabajo con múltiples hilos sin bloqueo explícito, ya que tradicionalmente ha sido la gran trampa del multihilo.

4

La respuesta corta es sí, son de un solo hilo.

La respuesta larga es que depende.

JRuby es multiproceso y se puede ejecutar en tomcat como otro código de Java. MRI (ruby predeterminado) y Python ambos tienen un GIL (Global Interpreter Lock) y por lo tanto tienen un solo hilo.

La forma en que funciona para los servidores web se complica aún más por la cantidad de configuraciones de servidores disponibles. Para la mayoría de las aplicaciones ruby ​​hay (al menos) dos niveles de servidores, un proxy/servidor de archivos estáticos como nginx y luego el servidor de la aplicación ruby.

Nginx no usa hilos como apache o tomcat, utiliza eventos no bloqueantes (y creo que procesos de trabajo bifurcados). Esto le permite tratar con niveles de concurrencia más altos que los permitidos con la sobrecarga y la ineficiencia de programación de subprocesos nativos.

Los diversos servidores de aplicaciones de ruby ​​también funcionan de diferentes maneras para obtener un alto rendimiento y concurrencia sin hilos. Thin usa libev y el modelo asincrónico como Nginx. Mongrel utiliza un grupo de procesos de trabajo por turnos. Unicorn utiliza IPC de Unix nativo (seleccione en un socket) para cargar el balance a un grupo de procesos bifurcados a través de un socket proxy maestro.

Los subprocesos son solo una forma de abordar la simultaneidad. Los procesos múltiples y los modelos destacados son un enfoque diferente que se relaciona bien con la base de Unix. Esto es fundamentalmente diferente de la forma en que Java trata al mundo.

+0

la respuesta corta es incorrecta, Python tiene múltiples hilos, es solo que la implementación C no permite la concurrencia verdadera de los hilos, pero aún tiene múltiples hilos. –

+0

¿Cuándo se activa el bloqueo de intérprete global para evitar un verdadero enviro multihilo? – Blankman

+1

El GIL protege un subproceso de Python para que no ingrese el bytecode interpeter si ya hay uno. Esto significa que * solo * que se ejecuta dentro del intérprete está protegido. Por ejemplo, múltiples hilos de Python que ejecutan código C desde extensiones C están perfectamente bien. Además, múltiples subprocesos C en ejecución también están bien. Lo único que no funciona es que múltiples hilos * Python * ejecutan código * Python *. (Por supuesto, las extensiones C pueden tener * sus propios * bloqueos. Y obviamente, si un hilo C de una extensión quiere ingresar al intérprete en nombre de un hilo de Python, entonces * it * también necesita obtener el GIL). –

5

CPython tiene un Global Interpreter Lock que puede reducir el rendimiento del código de subprocesos múltiples en Python. El efecto neto, en algunos casos, es que los hilos no se pueden ejecutar simultáneamente debido a la contención de bloqueo. No todas las implementaciones de Python usan un GIL, por lo que es posible que esto no se aplique a JPython, IronPython u otras implementaciones.

El lenguaje en sí admite operaciones de subprocesamiento y otras operaciones asincrónicas. Las bibliotecas de python también pueden admitir el proceso de subprocesamiento internamente sin exponerlo directamente al intérprete de Python.

Si usted ha oído nada negativo sobre Python y roscado (o que no lo soporta), es probable que alguien encontrarse con una situación en la que el GIL está causando un cuello de botella ..

2

Unos pocos Los lenguajes de programación interpretados como CPython y Ruby admiten subprocesos, pero tienen una limitación conocida como Global Intérprete de bloqueo (GIL). El GIL es un bloqueo exclusión mutua en poder del intérprete que impide que el intérprete de concurrentemente interpretar el código de aplicaciones en dos o más hilos al mismo tiempo, que limita efectivamente la concurrencia en varios sistemas centrales.

de Wikipedia Thread

+2

Antes que nada, no existe un "lenguaje de programación interpretado". La interpretación es un rasgo de la implementación, no del lenguaje; * cualquier * idioma puede ser implementado por un compilador o un intérprete, la mayoría son implementados por ambos. En segundo lugar, CPython no es el lenguaje de programación, es el lenguaje de programación * implementación *. En tercer lugar, ni siquiera es un intérprete, CPython es un * compilador *. En cuarto lugar, ni Python ni Ruby tienen un GIL. * Una * implementación de Python y * dos * (de una docena) implementaciones de Ruby tienen un GIL, pero una vez más, un GIL no es un rasgo del lenguaje, no el impl. –

0

La lectura de estas respuestas aquí ... Muchos de ellos tratan de sonar más inteligente de lo que realmente son en mi humilde opinión (im sobre todo hablando de cosas relacionadas con Rubí como esa es la que yo estoy más familiarizado con). De hecho, JRuby es actualmente la única implementación de Ruby que admite concurrencia verdadera. En JVM, los subprocesos de Ruby se asignan a subprocesos nativos del SO, sin que GIL interfiera. Así que es totalmente correcto decir que Ruby no es multiproceso. En 1.8.x, Ruby se ejecuta en realidad dentro de un subproceso del sistema operativo, y si bien tiene la sensación falsa de concurrencia con subprocesos verdes, entonces, en realidad, GIL evitará prácticamente que tenga verdadera concurrencia. En Ruby 1.9 esto cambió un poco, ya que ahora un proceso de Ruby puede tener muchos hilos del sistema operativo unidos a él (más los hilos verdes), pero de nuevo GIL destruirá totalmente el punto y se convertirá en el cuello de botella.

En la práctica, desde el punto de vista de una aplicación web normal, no debería importar mucho si es de una o varias capas. El problema surge principalmente en el lado del servidor de todos modos y en su mayoría es una cuestión de diferencia de escala de la técnica.

+0

"JRuby es actualmente la única implementación de Ruby que admite concurrencia verdadera": Wrong, IronRuby y MacRuby también lo hacen. "En JVM, los subprocesos de Ruby se asignan a subprocesos nativos del SO": Incorrecto, las dos implementaciones de Ruby en JVM (JRuby y XRuby) asignan subprocesos de Ruby a JVM estructurados, no a subprocesos nativos. (El mapeo a hilos nativos es prácticamente imposible en la JVM sin la piratería masiva de JNI C). "De modo que es totalmente correcto decir que Ruby no es multiproceso": Incorrecto. Solo dos oraciones antes de esto, en realidad has nombrado un contraejemplo que invalida tu reclamo. –

+0

"En 1.8.x, Ruby se ejecuta dentro de un hilo del sistema operativo": incorrecto. Varias implementaciones de Ruby 1.8 usan múltiples hilos de sistema operativo, por ejemplo, Rubinius. "[...] hilos verdes [...]": incorrecto. No hay nada en Ruby que diga que tienes que usar hilos verdes. De hecho, no hay nada en Ruby que prescriba algún tipo de implementación de subprocesos, verde, nativo o de otro tipo. La gran mayoría de las implementaciones de Ruby 1.8 (y las implementaciones de Ruby en general) eligen no usar hilos verdes, de hecho, solo una sola. –

+0

"sensación falsa de concurrencia con hilos verdes, entonces, en realidad, GIL prácticamente evitará que tenga verdadera concurrencia": Esto ni siquiera tiene sentido. Si solo tiene simultaneidad falsa, entonces no * necesita * un GIL porque no hay nada que proteger contra el acceso simultáneo, porque * no hay concurrencia en primer lugar *. Y, de hecho, la única implementación de Ruby que tiene hilos verdes * no * tiene un GIL.Las dos únicas implementaciones que * do * tienen un GIL son YARV y Rubinius, que usan subprocesos nativos. –

0

Sí Ruby and Python puede manejar multi-threading, pero para muchos casos (web) es mejor confiar en los hilos generados por las solicitudes http del cliente al servidor. Incluso si genera muchos subprocesos en una misma aplicación para reducir el costo del tiempo de ejecución o para manejar muchas tareas a la vez, en un caso de aplicación web que suele ser demasiado tiempo, nadie esperará felizmente más que algunas fracciones de segundo para la respuesta de su aplicación en una sola página, es más inteligente usar técnicas AJAX (Asynchronous JavaScript And XML): asegúrese de que el diseño de su web se muestre rápidamente y realice una inserción asíncrona de esas cosas de codificación difícil más adelante.

¡Eso no quiere decir que el multihilo sea inútil para la web! Se recomienda encarecidamente bajar la carga de tu servidor si quieres ejecutar recursive-complicated-hardcore-applications (no para un sitio web, quiero decir), pero lo que devuelve eso debe terminar en archivos o en bases de datos, entonces podría ser suavemente servido por una respuesta http.

6

Una pregunta confusa con muchas respuestas confusas ...

En primer lugar, roscado y ejecución concurrente son cosas diferentes. Python admite los hilos muy bien; no admite la ejecución concurrente en ninguna implementación en el mundo real. (En todas las implementaciones graves, solo se puede ejecutar un subproceso de VM a la vez; todos los intentos de desacoplamiento de subprocesos de VM han fallado).

En segundo lugar, esto es irrelevante para las aplicaciones web. No es necesario que los servidores de fondo de Python se ejecuten al mismo tiempo en el mismo proceso. Genera procesos separados para cada back-end, que luego pueden manejar solicitudes en paralelo porque no están vinculados entre sí.

Usar subprocesos para backends web es una mala idea. ¿Por qué introducir los peligros de enhebrar (bloqueo, condiciones de carrera, puntos muertos) a algo intrínsecamente embarazosamente paralelo? Es mucho más seguro esconder cada backend en su propio proceso aislado, evitando el potencial de todos estos problemas.

(Hay ventajas de compartir el espacio de memoria - que ahorra memoria, mediante el intercambio de código estático -, sino que se pueden resolver sin hilos.)

+0

Estoy bastante seguro de que de las cuatro implementaciones de Python en el mundo real, las tres * do * admiten subprocesos verdaderamente simultáneos. O, para ser más precisos, hilos sincronizados por bloqueos de grano muy fino ubicados estratégicamente alrededor de unas estructuras de datos muy pequeñas en lugar de un bloqueo de monstruo gigante en todo el intérprete. –

+0

Depende de su definición de "mundo real", por supuesto, pero no afirmaré que he probado todas las implementaciones tampoco. –

+0

"Generas procesos separados para cada backend" Esto puede ser un gran problema de memoria/recursos, ¿y si necesito generar más de 50 procesos? es mucho más fácil sincronizar los hilos como menciona Jorg antes, colocar los bloqueos en lugares estratégicos y administrarlos de esa forma en lugar de generar un nuevo proceso para cada tarea. – Syler

Cuestiones relacionadas