Primero: una CPU no tiene "subprocesos", a pesar de lo que el mercado de marketing intenta reclamar. Una CPU puede ejecutar hasta el número indicado de subprocesos al mismo tiempo. Específicamente, una CPU con n núcleos y hyperthreading no habilitado puede ejecutar n hilos. Una CPU con n núcleos y hyperthreading habilitado puede ejecutar subprocesos 2_n_. En contextos técnicos nos referimos a "lo que puede ejecutar un hilo" como un procesador lógico o LP. Una máquina sin HT habilitado tiene un LP por núcleo; HT le da dos.
Un sistema típico de Windows tiene cientos o incluso miles de subprocesos, en total, al mismo tiempo. Esto depende del código de cada programa individual para decidir. Cuando crea un proceso, ese proceso siempre comienza con un hilo. Algunos programas simples, particularmente los programas de línea de comandos (modo de caracteres), pueden usar solo un hilo. Pero el código que se ejecuta en ese primer hilo puede crear otros hilos, y esos hilos pueden crear otros hilos, y así sucesivamente, casi sin un límite práctico. Hay buenas razones para no simplemente crear una gran cantidad de hilos, pero no hay nada que haga imposible crear muchos más hilos de los que uno podría usar.
(En x86, con los valores predeterminados para el tamaño de la pila de subprocesos, hay un límite de aproximadamente 2000 subprocesos por proceso, impuesto por el límite de espacio de direcciones).
En la pestaña Detalles del Administrador de tareas, puede habilitar la columna Subprocesos, que le indicará cuántos subprocesos hay en cada proceso en este momento. Aquí hay un comando de PowerShell que contará todos los hilos en su sistema:
($threads = get-ciminstance win32_thread).count
3437
Esto está en una máquina con cuatro núcleos hiperprocesados, un total de ocho LP.
Esto no es un problema porque solo unos pocos de esos hilos realmente quieren ejecutarse en cualquier momento. La mayoría de los subprocesos en la mayoría de los procesos pasaron la mayor parte de su tiempo en lo que Windows llama un estado de "espera", lo que significa que no quieren o no pueden usar el tiempo de CPU en este momento. Están esperando que se complete la E / S (tal vez la red, tal vez el disco, etc.), están esperando la entrada del usuario, están esperando que algún otro hilo libere un recurso al que necesitan acceder, etc. * los sistemas derivados de nix llaman a esto "bloqueado".)
Si desea la cantidad de hilos que están en espera, intente esto:
PS C:\Users\jeh> ($threads = get-ciminstance win32_thread | where-object -Property ThreadState -EQ 5).count
3427
Parece que solo hay 10 hilos tratando de usar los LP en este momento. Pero es incluso mejor que eso. Con 8 LP, 8 de esos hilos son los hilos inactivos del sistema. Hay un hilo inactivo dedicado a cada LP. Siempre están listos para correr, pero solo corren si nada más quiere el LP. Entonces, en el momento en que hice los comandos anteriores, solo había dos hilos "reales" que querían hacer el trabajo. Las actividades de los subprocesos inactivos no se incluyen en las pantallas de gráficos de líneas del Administrador de tareas de la utilización de la CPU.
Nota: estos números no son muy precisos porque estas operaciones de Powershell y WMI no están sincronizadas internamente con las funciones del sistema operativo. Pero son lo suficientemente cercanos como para ilustrar el punto.
Si hay más subprocesos (aparte de los subprocesos inactivos) "Listos" que los LP, entonces el planificador, en general, elige los subprocesos nLP de mayor prioridad , sujeto a algunos ajustes según quién ejecutó en qué CPU recientemente. Si hay varios subprocesos con la misma prioridad, pueden "dividirse en el tiempo" y ejecutarse de forma "circular", y cada uno puede ejecutarse durante 20 o 60 ms antes de que el programador cambie el LP a otro.
Aquí hay una respuesta que di que entra en más detalles sobre cómo funcionan las prioridades de subprocesos en Windows.