multithreading - usar - ¿Cuál es la diferencia entre un hilo y una fibra?
que son los hilos en programacion (10)
A Fiber es un hilo ligero que usa multitareas cooperativas en lugar de multitareas preventivas. Una fibra en ejecución debe "ceder" explícitamente para permitir que se ejecute otra fibra, lo que hace que su implementación sea mucho más fácil que los hilos del kernel o del usuario.
Un Coroutine es un componente que generaliza una subrutina para permitir puntos de entrada múltiples para suspender y reanudar la ejecución en ciertas ubicaciones. A diferencia de las subrutinas, las corutinas pueden salir llamando a otras corutinas, que luego pueden volver al punto en el que se invocaron en la corutina original.
¿Cuál es la diferencia entre un hilo y una fibra? He oído hablar de fibras de rubí y he leído que están disponibles en otros idiomas, ¿podría alguien explicarme en términos simples cuál es la diferencia entre un hilo y una fibra?
En Win32, una fibra es una especie de hilo administrado por el usuario. Una fibra tiene su propia pila y su propio puntero de instrucción, etc., pero el sistema operativo no programa las fibras: debe llamar a SwitchToFiber explícitamente. Los subprocesos, por el contrario, son programados de manera preventiva por el sistema operativo. En términos generales, una fibra es un hilo que se gestiona en el nivel de aplicación / tiempo de ejecución en lugar de ser una verdadera hebra del sistema operativo.
Las consecuencias son que las fibras son más baratas y que la aplicación tiene más control sobre la programación. Esto puede ser importante si la aplicación crea muchas tareas simultáneas y / o desea optimizar de cerca cuando se ejecutan. Por ejemplo, un servidor de base de datos puede elegir usar fibras en lugar de hilos.
(Puede haber otros usos para el mismo término; como se señaló, esta es la definición de Win32).
En los términos más simples, los hilos generalmente se consideran preventivos (aunque esto puede no ser siempre cierto, dependiendo del sistema operativo) mientras que las fibras se consideran hilos cooperativos ligeros. Ambas son rutas de ejecución separadas para su aplicación.
Con subprocesos: la ruta de ejecución actual puede interrumpirse o adelantarse en cualquier momento (nota: esta afirmación es una generalización y puede que no siempre sea verdadera según el paquete OS / threading / etc.). Esto significa que para los hilos, la integridad de los datos es un gran problema porque un hilo se puede detener en el medio de actualizar una porción de datos, dejando la integridad de los datos en un estado malo o incompleto. Esto también significa que el sistema operativo puede aprovechar múltiples CPU y núcleos de CPU ejecutando más de un hilo al mismo tiempo y dejándolo al desarrollador para proteger el acceso a los datos.
Con fibras: la ruta de ejecución actual solo se interrumpe cuando la fibra produce la ejecución (misma nota que la anterior). Esto significa que las fibras siempre comienzan y se detienen en lugares bien definidos, por lo que la integridad de los datos es mucho menos problemática. Además, como las fibras a menudo se gestionan en el espacio del usuario, no es necesario realizar costosos cambios de contexto ni cambios en el estado de la CPU, lo que hace que el cambio de una fibra a otra sea extremadamente eficiente. Por otro lado, dado que no se pueden ejecutar dos fibras exactamente al mismo tiempo, el solo uso de fibras por sí solo no aprovechará múltiples CPU o múltiples núcleos de CPU.
La definición de fibra Win32 es, de hecho, la definición de "Green Thread" establecida en Sun Microsystems. No es necesario perder el término fibra en el hilo de algún tipo, es decir, un subproceso que se ejecuta en el espacio de usuario bajo el código de usuario / control de biblioteca de subprocesos.
Para aclarar el argumento, mira los siguientes comentarios:
- Con Hyper-threading, la CPU multi-core puede aceptar múltiples hilos y distribuirlos uno en cada núcleo.
- La CPU encadenada superescalar acepta un subproceso para la ejecución y utiliza el paralelismo de nivel de instrucción (ILP) para ejecutar el subproceso más rápido. Podemos suponer que un hilo se rompe en fibras paralelas que corren en tuberías paralelas.
- La CPU SMT puede aceptar múltiples hilos y frenarlos en fibras de instrucciones para la ejecución paralela en múltiples tuberías, utilizando tuberías de manera más eficiente.
Deberíamos suponer que los procesos están hechos de hilos y que los hilos deberían estar hechos de fibras. Con esa lógica en mente, usar fibras para otros tipos de hilos es incorrecto.
Los hilos están programados por el SO (preventivo). El sistema operativo puede detener o reanudar un hilo en cualquier momento, pero las fibras se administran más o menos (cooperativas) y ceden el uno al otro. Es decir, el programador controla cuando las fibras hacen su procesamiento y cuando ese procesamiento cambia a otra fibra.
Los hilos generalmente se basan en el kernel para interrumpir el hilo para que se pueda ejecutar u otro subproceso (que es mejor conocido como multitarea preventiva) mientras que las fibras usan multitarea cooperativa donde es la fibra misma la que renuncia a su tiempo de ejecución para que otras fibras pueden funcionar.
Algunos enlaces útiles que lo explican mejor de lo que probablemente hice son:
Los hilos se crearon originalmente como procesos livianos. De manera similar, las fibras son un hilo ligero, que confía (de forma simplista) en las fibras mismas para programarse entre sí, al ceder el control.
Supongo que el siguiente paso será hebras donde tienes que enviarles una señal cada vez que quieras que ejecuten una instrucción (no muy diferente a mi hijo de 5 años :-). En los viejos tiempos (e incluso ahora en algunas plataformas integradas), todos los hilos eran fibras, no había preferencia y tenías que escribir tus hilos para comportarse bien.
Los hilos utilizan la programación preventiva , mientras que las fibras usan la programación cooperativa .
Con un hilo, el flujo de control podría interrumpirse en cualquier momento, y otro hilo puede tomar el control. Con múltiples procesadores, puede tener múltiples hilos ejecutándose todos al mismo tiempo (multiprocesamiento simultáneo o SMT). Como resultado, debe tener mucho cuidado con el acceso concurrente a los datos y proteger sus datos con mutexes, semáforos, variables de condición, etc. A menudo es muy complicado acertar.
Con una fibra, el control solo cambia cuando se lo indica, generalmente con una llamada a función llamada algo como yield()
. Esto facilita el acceso simultáneo a los datos, ya que no tiene que preocuparse por la atomicidad de las estructuras de datos o los mensajes muteos. Mientras no cedas, no hay peligro de que te eluden y tengas otra fibra tratando de leer o modificar los datos con los que estás trabajando. Como resultado, sin embargo, si la fibra entra en un ciclo infinito, no se puede ejecutar ninguna otra fibra, ya que no cede.
También puede mezclar hilos y fibras, lo que da lugar a los problemas que enfrentan ambos. No se recomienda, pero a veces puede ser lo correcto si se hace con cuidado.
Primero, recomendaría leer esta explicación de la diferencia entre procesos e hilos como material de fondo.
Una vez que haya leído que es bastante sencillo. Los hilos se pueden implementar en el kernel, en el espacio de usuario, o los dos se pueden mezclar. Las fibras son básicamente hilos implementados en el espacio del usuario.
- Lo que típicamente se llama un hilo es un hilo de ejecución implementado en el kernel: lo que se conoce como hilo del kernel. La programación de un hilo del kernel es manejada exclusivamente por el kernel, aunque un hilo del kernel puede liberar voluntariamente el CPU durmiendo si lo desea. Un hilo del núcleo tiene la ventaja de que puede usar E / S de bloqueo y le permite al núcleo preocuparse por la programación. Su principal desventaja es que la conmutación de subprocesos es relativamente lenta, ya que requiere atrapamiento en el kernel.
- Las fibras son hilos de espacio de usuario cuya programación se maneja en el espacio de usuario por uno o más hilos del kernel en un único proceso. Esto hace que la conmutación de fibra sea muy rápida. Si agrupa todas las fibras que acceden a un conjunto particular de datos compartidos en el contexto de una única hebra del kernel y su programación se maneja con una sola hebra del kernel, puede eliminar los problemas de sincronización ya que las fibras se ejecutarán efectivamente en serie y habrá completado control sobre su programación. Agrupar las fibras relacionadas bajo un único hilo de kernel es importante, ya que el núcleo puede anticipar el hilo del kernel en el que se están ejecutando. Este punto no está claro en muchas de las otras respuestas. Además, si usa E / S de bloqueo en una fibra, todo el hilo del kernel es una parte de los bloques, incluidas todas las fibras que forman parte de esa cadena del kernel.
En la sección 11.4 "Procesos e hilos en Windows Vista" en los sistemas operativos modernos, Tanenbaum comenta:
Aunque las fibras se programan de forma cooperativa, si hay múltiples hilos programando las fibras, se requiere mucha sincronización cuidadosa para garantizar que las fibras no interfieran entre sí. Para simplificar la interacción entre subprocesos y fibras, a menudo es útil crear solo tantos subprocesos como procesadores para ejecutarlos, y afinitizar los subprocesos para cada ejecución solo en un conjunto distinto de procesadores disponibles, o incluso solo un procesador. Cada hilo puede ejecutar un subconjunto particular de las fibras, estableciendo una relación uno a muchos entre hilos y fibras que simplifica la sincronización. Aun así, todavía hay muchas dificultades con las fibras. La mayoría de las bibliotecas Win32 desconocen por completo las fibras, y las aplicaciones que intentan usar fibras como si fueran hilos encontrarán varios fallos. El núcleo no tiene conocimiento de las fibras, y cuando una fibra ingresa al kernel, el hilo en el que se está ejecutando puede bloquearse y el kernel programará un hilo arbitrario en el procesador, lo que lo hará no disponible para ejecutar otras fibras. Por estas razones, las fibras rara vez se usan, excepto cuando se transfieren códigos de otros sistemas que requieren explícitamente la funcionalidad provista por las fibras.
Tenga en cuenta que, además de los subprocesos y las fibras, Windows 7 presenta la programación en modo usuario :
La programación en modo de usuario (UMS) es un mecanismo liviano que las aplicaciones pueden usar para programar sus propios hilos. Una aplicación puede alternar entre subprocesos UMS en modo de usuario sin involucrar al planificador del sistema y recuperar el control del procesador si un subproceso UMS bloquea en el kernel. Los subprocesos de UMS difieren de las fibras en que cada subproceso de UMS tiene su propio contexto de subproceso en lugar de compartir el contexto de subproceso de un solo subproceso. La capacidad de cambiar entre subprocesos en el modo de usuario hace que UMS sea más eficiente que los grupos de subprocesos para administrar grandes cantidades de elementos de trabajo de corta duración que requieren pocas llamadas al sistema.
Para obtener más información sobre hilos, fibras y UMS, vea Dave Probert: Inside Windows 7 - User Mode Scheduler (UMS) .