Solo soy un usuario casual de Go, así que toma lo siguiente con un grano de sal.
Wikipedia define subprocesos verdes como "subprocesos programados por una máquina virtual (VM) en lugar de de forma nativa por el subyacente sistema operativo". Los subprocesos verdes emulan entornos de subprocesos múltiples sin depender de las capacidades del sistema operativo nativo, y se administran en el espacio del usuario en lugar del espacio del núcleo, lo que les permite trabajar en entornos que no tienen soporte de subprocesos nativos.
Go (o, más exactamente, las dos implementaciones existentes) es un lenguaje que produce solo código nativo, no utiliza una máquina virtual. Además, el programador en las implementaciones de tiempo de ejecución actuales se basa en subprocesos de nivel de sistema operativo (incluso cuando GOMAXPROCS = 1). Así que creo que hablar de hilos verdes para el modelo Go es un poco abusivo.
Go people ha acuñado el término goroutine especialmente para evitar la confusión con otros mecanismos de concurrencia (como coroutines o hilos o procesos ligeros).
Por supuesto, Go admite un modelo de subprocesos M: N, pero se parece mucho más al modelo de procesos de Erlang que al modelo de subprocesos de Java verde.
Aquí hay algunos beneficios del modelo Go sobre los hilos verdes (como se implementó a principios de JVM):
-
Múltiples núcleos o CPU se pueden usar de manera transparente, de manera transparente para el desarrollador. Con Go, el desarrollador debe hacerse cargo de la concurrencia. El tiempo de ejecución Go se encargará del paralelismo. Las implementaciones de subprocesos verdes de Java no se escalaron en múltiples núcleos o CPU.
-
El sistema y las llamadas C no bloquean el programador (todas las llamadas del sistema, no solo las que admiten E / S multiplexadas en los bucles de eventos). Las implementaciones de hilos verdes podrían bloquear todo el proceso cuando se realizó una llamada al sistema de bloqueo.
-
Copias o pilas segmentadas. En Go, no es necesario proporcionar un tamaño de pila máximo para el goroutine. La pila crece incrementalmente según sea necesario. Una consecuencia es que una goroutina no requiere mucha memoria (4KB-8KB), por lo que una gran cantidad de ellos puede ser generada felizmente. Por lo tanto, el uso de Goroutine puede ser generalizado.
Ahora, para abordar las críticas:
-
Con Go, no tiene que escribir un programador de espacio de usuario: ya está provisto con el tiempo de ejecución. Es un software complejo, pero es el problema de los desarrolladores de Go, no de los usuarios de Go. Su uso es transparente para los usuarios de Go. Entre los desarrolladores de Go, Dmitri Vyukov es un experto en programación lockfree / waitfree, y parece estar especialmente interesado en abordar los posibles problemas de rendimiento. del programador. La implementación del planificador actual no es perfecta, pero mejorará.
-
La sincronización trae problemas de rendimiento y complejidad: esto también es cierto en parte con Go. Pero tenga en cuenta que el modelo Go intenta promover el uso de canales y una descomposición limpia del programa en goroutines concurrentes para limitar la complejidad de la sincronización (es decir, compartir datos mediante la comunicación, en lugar de compartir la memoria para comunicarse). Por cierto, la implementación de Go de referencia proporciona una serie de herramientas para abordar problemas de rendimiento y concurrencia, como un perfilador , y un detector de raza .
-
En cuanto a la falla de la página y "falsificación de múltiples subprocesos", tenga en cuenta que Go puede programar la goroutine en varios subprocesos del sistema. Cuando se bloquea un hilo por cualquier motivo (error de página, bloqueo de llamadas al sistema), no impide que los otros hilos sigan programando y ejecutando otras goroutines. Ahora, es cierto que un error de página bloqueará el subproceso del sistema operativo, y se supone que todos los goroutines se programarán en este subproceso. Sin embargo, en la práctica, la memoria del montón Go no se debe intercambiar. Esto sería lo mismo en Java: de todos modos, los lenguajes recolectados en basura no acomodan muy bien la memoria virtual. Si su programa debe manejar la falla de la página de una manera elegante, si es probable, ya que tiene que administrar algo de memoria fuera del montón. En ese caso, envolver el código correspondiente con las funciones de acceso C simplemente resolverá el problema (porque nuevamente las llamadas C o el bloqueo de llamadas al sistema nunca bloquean el programador de tiempo de ejecución de Go).
OMI, los goroutines no son hilos verdes, y el lenguaje Go y la implementación actual abordan principalmente estas críticas.