Cuando duermes un hilo, ¿qué está pasando realmente?
Veo que dormir un hilo "detiene el hilo actual durante un período de tiempo determinado" . Pero, ¿cómo funciona?
Según How Thread.sleep () funciona internamente y ¿Cómo funciona realmente Thread.sleep? :
- la duración del sueño estará sujeta a alguna granularidad específica del sistema
- el sueño está bloqueando
- el hilo sale de la CPU y detiene su ejecución
- el hilo no consume tiempo de CPU mientras duerme
Simplemente no puedo entender la mecánica interna y fundamental de lo que todo esto significa.
Entiendo que hay algo llamado planificador que es responsable de cambiar entre hilos.
Las fuentes parecen indicar que esto varía según el sistema operativo (¿o el hardware?) Y la mayoría de los subprocesos reciben entre 1 ms y 60 ms aproximadamente para realizar algunas acciones antes de que la CPU cambie a otro subproceso.
Pero cuando un hilo duerme (por ejemplo, muchos segundos), ¿cómo se reanuda? Supongo que un temporizador está involucrado de alguna manera, ¿es el reloj de la placa base? ¿Está relacionado con la velocidad del reloj de la CPU?
E incluso si se trata de un temporizador, ¿cómo sabe la CPU cuándo es hora de volver a prestar atención al hilo? ¿No tendría que revisar constantemente el hilo para ver si está listo? ¿No es efectivamente de votación y por lo tanto la clase de está consumiendo tiempo de CPU?
¿Está durmiendo un subproceso específico del idioma o es el sistema operativo responsable de él o es algo específico de la CPU?
¿Alguien podría explicarme esto con explicaciones básicas de cosas como el planificador y lo que está haciendo la CPU durante todo esto?
fuente
Respuestas:
Hay mucho más involucrado en la ejecución de un programa que solo el código dentro de ese programa.
Cualquier programa que se ejecute en un sistema operativo multiproceso está bajo el control del planificador del sistema operativo , y el planificador mantiene una tabla explícita que indica qué proceso se está ejecutando, cuáles están esperando para ejecutarse cuando hay ciclos de CPU disponibles y cuáles ni siquiera tratando de correr (durmiendo). El planificador generalmente asigna segmentos de tiempo de tamaño par a los procesos dependiendo de su prioridad y su historial de ejecución. En última instancia, este bucle es impulsado por interrupciones de hardware, generalmente generadas por un oscilador en la placa principal.
Dormir siempre es una característica que un lenguaje de programación puede admitir solo porque el entorno de tiempo de ejecución donde se ejecutará lo admite. Un programa normal no puede suspenderse solo , solo puede decirle al programador cómo le gustaría que lo traten, y el programador no está obligado ni es capaz de satisfacer ese deseo. Piense en una computadora portátil cerrada y en hibernación; el oscilador de la placa principal sigue pulsando, pero dado que el programador no se está ejecutando, tampoco se puede ejecutar ningún proceso, sin importar cuán alta sea su prioridad.
fuente
Como Doc Brown mencionó en un comentario, las interrupciones son la clave, y no solo para dormir.
Una interrupción es una señal de hardware de que el procesador debe detener lo que está haciendo y ejecutar un fragmento de código. Los dispositivos externos provocan interrupciones cuando necesitan la atención del procesador: por ejemplo, cuando un disco ha terminado de leer datos, o se ha presionado una tecla, o un temporizador de cuenta regresiva en la placa base ha llegado a cero.
El código de manejo de interrupciones es generalmente muy pequeño y muy rápido. Por ejemplo, cuando el disco indica que se ha copiado un bloque en la memoria, el sistema operativo simplemente puede registrar ese hecho en una lista de "bloques listos" en algún lugar y luego volver a lo que sea que estaba haciendo. No desea que la CPU pase todo su tiempo en código de manejo de interrupciones y no ejecute código de usuario.
Una pieza de código de interrupción que no es necesariamente pequeña es el planificador. Se activa por una señal de un temporizador de cuenta regresiva y examina el estado del sistema cada vez que se ejecuta. Esto generalmente incluirá la identificación de procesos que están listos para ejecutarse (por ejemplo, porque el bloque que estaban esperando ha llegado a la memoria), así como aquellos que han agotado su segmento de tiempo.
Entonces, cuando ejecuta una suspensión de subprocesos, lo que está haciendo es decirle al sistema operativo que (1) está renunciando a su segmento de tiempo, y (2) no debe despertarse nuevamente hasta que haya transcurrido un cierto tiempo.
Cada vez que se ejecuta el planificador, observará su hilo y solo lo marcará como "listo para ejecutarse" si ha transcurrido ese tiempo. Esto es un sondeo, de algún tipo, pero no es un sondeo de "bucle ocupado" ya que se desencadena por una interrupción. Tampoco es tan costoso: por lo general, solo hay un millar de hilos ejecutándose a la vez.
Esto también debería darle una idea de por qué los tiempos de reposo no son exactos: cuando su subproceso esté listo para ejecutarse, puede haber otros subprocesos que aún se estén ejecutando y que no hayan agotado su intervalo de tiempo. O puede haber subprocesos de mayor prioridad que estén listos para ejecutarse.
fuente