¿Cómo se logra la funcionalidad de subprocesos múltiples en un lenguaje de alto nivel, como Java, utilizando solo un subproceso y una máquina de estado? Por ejemplo, ¿qué pasa si hay 2 actividades para realizar (hacer cálculos y hacer E / S) y una actividad puede bloquear?
Lo que está describiendo se llama multitarea cooperativa , donde las tareas se asignan a la CPU y se espera que renuncien voluntariamente después de una cantidad de tiempo o actividad autodeterminada. Una tarea que no coopera al continuar usando la CPU o al bloquear las encías en todo el trabajo y sin tener un temporizador de vigilancia de hardware, no hay nada que el código que supervise las tareas pueda hacer al respecto.
Lo que ves en los sistemas modernos se llama multitarea preventiva , que es donde las tareas no tienen que renunciar a la CPU porque el supervisor lo hace por ellas cuando llega una interrupción generada por hardware. La rutina de servicio de interrupción en el supervisor guarda el estado de la CPU y la restaura la próxima vez que se considere que la tarea merece un intervalo de tiempo, luego restaura el estado de la tarea que se ejecutará a continuación y vuelve a saltar como si nada hubiera sucedido . Esta acción se llama cambio de contexto y puede ser costosa.
¿Está usando la alternativa "solo máquina de estado" como alternativa viable al multihilo en lenguajes de alto nivel?
¿Viable? Seguro. ¿Cuerdo? A veces. Si usa hilos o alguna forma de multitarea cooperativa casera (por ejemplo, máquinas de estado) depende de las compensaciones que esté dispuesto a hacer.
Los subprocesos simplifican el diseño de tareas hasta el punto en que puede tratar a cada uno como su propio programa que comparte espacio de datos con otros. Esto le da la libertad de concentrarse en el trabajo en cuestión y no toda la administración y el servicio de limpieza necesarios para que funcione una iteración a la vez. Pero como ninguna buena acción queda impune, usted paga por toda esta conveniencia en los cambios de contexto. Tener muchos subprocesos que producen la CPU después de hacer un trabajo mínimo (voluntariamente o haciendo algo que se bloquearía, como E / S) puede consumir mucho tiempo del procesador al cambiar de contexto. Esto es especialmente cierto si sus operaciones de bloqueo raramente bloquean por mucho tiempo.
Hay algunas situaciones en las que la ruta cooperativa tiene más sentido. Una vez tuve que escribir algún software de usuario para una pieza de hardware que transmitía muchos canales de datos a través de una interfaz mapeada en memoria que requería sondeo. Cada canal era un objeto construido de tal manera que podía dejarlo correr como un hilo o ejecutar repetidamente un solo ciclo de sondeo.
El rendimiento de la versión multiproceso no fue bueno en absoluto por exactamente la razón que describí anteriormente: cada hilo estaba haciendo un trabajo mínimo y luego producía la CPU para que los otros canales pudieran tener algo de tiempo, causando muchos cambios de contexto. Permitir que los subprocesos se ejecuten libremente hasta evitarlos ayudó con el rendimiento, pero resultó en que algunos canales no recibieran servicio antes de que el hardware experimentara un desbordamiento del búfer porque no obtuvieron un intervalo de tiempo lo suficientemente pronto.
La versión de un solo subproceso, que hizo incluso iteraciones de cada canal, corrió como un simio escaldado y la carga en el sistema cayó como una roca. La penalización que pagué por el rendimiento adicional fue tener que hacer malabarismos con las tareas yo mismo. En este caso, el código para hacerlo fue lo suficientemente simple como para que el costo de desarrollarlo y mantenerlo valiera la pena para mejorar el rendimiento. Supongo que es realmente el resultado final. Si mis hilos hubieran estado esperando a que volviera alguna llamada del sistema, el ejercicio probablemente no hubiera valido la pena.
Eso me lleva al comentario de Cox: los hilos no son exclusivamente para personas que no pueden escribir máquinas de estado. Algunas personas son bastante capaces de hacerlo, pero eligen usar una máquina de estados enlatada (es decir, un hilo) con el interés de hacer el trabajo antes o con menos complejidad.