Subprocesos múltiples
La versión actual de la página aún no ha sido revisada por colaboradores experimentados y puede diferir significativamente de la
versión revisada el 16 de marzo de 2016; las comprobaciones requieren
43 ediciones .
Multithreading ( eng. Multithreading ) es una propiedad de una plataforma (por ejemplo, un sistema operativo , una máquina virtual , etc.) o una aplicación , que consiste en que un proceso generado en el sistema operativo puede consistir en varios hilos en ejecución " en paralelo ", luego comer sin un orden prescrito en el tiempo . Para algunas tareas, esta separación puede lograr un uso más eficiente de los recursos informáticos .
Estos subprocesos también se denominan subprocesos de ejecución (del inglés subproceso de ejecución ); a veces llamados "hilos" (traducción literal del inglés hilo ) o informalmente "hilos".
Descripción
La esencia de los subprocesos múltiples es cuasi multitarea a nivel de un proceso ejecutable, es decir, todos los subprocesos se ejecutan en el espacio de direcciones del proceso. Además, todos los subprocesos de un proceso comparten no solo un espacio de direcciones común, sino también descriptores de archivo comunes . Un proceso en ejecución tiene al menos un subproceso (maestro).
Multithreading (como doctrina de programación ) no debe confundirse con multitarea o multiprocesamiento , aunque los sistemas operativos que implementan multitarea tienden a implementar multithreading también.
Las ventajas de una implementación multiproceso de un sistema en particular sobre uno multitarea incluyen lo siguiente:
- Simplificando el programa en algunos casos usando un espacio de direcciones común.
- Menos tiempo dedicado a crear un hilo en relación con el proceso.
Las ventajas de una implementación de subprocesos múltiples de un sistema en particular sobre uno de un solo subproceso incluyen lo siguiente:
- Simplificación del programa en algunos casos, debido a la eliminación de los mecanismos para intercalar la ejecución de varias subtareas débilmente interconectadas que requieren ejecución simultánea, en un subsistema de subprocesamiento múltiple separado.
- Mejora del rendimiento del proceso al paralelizar los cálculos del procesador y las operaciones de E/S.
En el caso de que los subprocesos de ejecución requieran una interacción relativamente compleja entre sí, pueden ocurrir problemas de multitarea, como interbloqueos.
Implementación de hardware
En un procesador convencional, la gestión de subprocesos está a cargo del sistema operativo. El subproceso se ejecuta hasta que se produce una interrupción de hardware, se produce una llamada al sistema o hasta que expira el tiempo asignado por el sistema operativo. Después de eso, el procesador cambia al código del sistema operativo, que guarda el estado del hilo (su contexto) o cambia al estado de otro hilo, al que también se le asigna tiempo para la ejecución. Con tales subprocesos múltiples, se gasta una cantidad suficientemente grande de ciclos de procesador en el código del sistema operativo que cambia de contexto. Si el soporte de subprocesos se implementa en el hardware, entonces el propio procesador podrá cambiar entre subprocesos y, en el caso ideal, ejecutar varios subprocesos simultáneamente para cada ciclo de reloj. Para el sistema operativo y el usuario, uno de esos procesadores físicos será visto como múltiples procesadores lógicos.
Hay dos formas de subprocesos múltiples que se pueden implementar en procesadores en hardware:
Tipos de implementación de subprocesos
- Un hilo en el espacio del usuario. Cada proceso tiene una tabla de subprocesos similar a la tabla de procesos del núcleo. Las desventajas incluyen:
- Sin interrupción de temporizador dentro del mismo proceso
- Cuando utiliza una solicitud del sistema de bloqueo en un proceso, todos sus subprocesos se bloquean.
- Complejidad de implementación
- Flujo en el espacio del núcleo. Junto con la tabla de procesos, hay una tabla de subprocesos en el espacio del núcleo.
- "Fibras" ( ing. fibras ). Múltiples subprocesos en modo usuario que se ejecutan en un solo subproceso en modo kernel. Un subproceso de espacio del kernel consume recursos notables, principalmente memoria física y un rango de direcciones de modo kernel para la pila de modo kernel. Por lo tanto, se introdujo el concepto de "fibra", un subproceso ligero que se ejecuta exclusivamente en modo de usuario. Cada hilo puede tener múltiples "fibras".
Interacción de subprocesos
En un entorno de subprocesos múltiples, a menudo hay tareas que requieren la suspensión y reanudación de algunos subprocesos en función del trabajo de otros. En particular, se trata de tareas relacionadas con la prevención de conflictos de acceso al utilizar los mismos datos o dispositivos de hilos ejecutables paralelos. Para resolver tales problemas, se utilizan objetos especiales para la interacción de hilos, como exclusiones mutuas (mutexes), semáforos, secciones críticas, eventos, etc. Muchos de estos objetos son objetos del kernel y se pueden usar no solo entre subprocesos del mismo proceso, sino también para la interacción entre subprocesos de diferentes procesos.
- Un mutex es un objeto de sincronización que se establece en un estado señalado especial cuando no está ocupado por ningún subproceso. Solo un subproceso posee este objeto en cualquier momento, de ahí el nombre de dichos objetos (del inglés acceso mutuamente exclusivo - acceso mutuamente exclusivo) - se excluye el acceso simultáneo a un recurso compartido . Después de todas las acciones necesarias, se libera el mutex, dando acceso a otros subprocesos al recurso compartido. Un objeto puede admitir la captura recursiva una segunda vez por el mismo subproceso, incrementando el contador sin bloquear el subproceso y luego requiriendo múltiples liberaciones. Tal, por ejemplo, es la sección crítica en Win32 . Sin embargo, hay algunas implementaciones que no admiten esto y provocan que el subproceso se interbloquee al intentar una captura recursiva. Por ejemplo, esto es FAST_MUTEX en el kernel de Windows.
- Las secciones críticas proporcionan una sincronización similar a los mutex, excepto que los objetos que representan las secciones críticas solo son accesibles dentro de un único proceso. Los eventos, mutexes y semáforos también se pueden usar en subprocesos de aplicaciones de un solo proceso; sin embargo, las implementaciones de secciones críticas en algunos sistemas operativos (por ejemplo, Windows NT) proporcionan un mecanismo más rápido y eficiente [1] [2] para procesos mutuamente excluyentes . sincronización: "obtener" y "liberar" en la sección crítica están optimizados para el caso de un solo subproceso (sin contención) para evitar cualquier llamada al sistema que conduzca al kernel del sistema operativo.
- Los semáforos son recursos disponibles que varios subprocesos pueden adquirir al mismo tiempo hasta que el grupo de recursos esté vacío. Luego, los subprocesos adicionales deben esperar hasta que la cantidad requerida de recursos esté disponible nuevamente.
- Desarrollos. Objeto que almacena 1 bit de información “señalado o no”, sobre el cual se definen las operaciones “señalar”, “restablecer a un estado no señalizado” y “esperar”. Esperar un evento señalado es la ausencia de una operación con una continuación inmediata de la ejecución del hilo. Esperar un evento no señalado hace que la ejecución de un subproceso se suspenda hasta que otro subproceso (o la segunda fase de un controlador de interrupciones en el kernel del sistema operativo) señala el evento. Es posible esperar varios eventos en los modos "cualquiera" o "todos". También es posible crear un evento que se restablezca automáticamente a un estado no señalado después de activar el primer y único subproceso en espera (dicho objeto se utiliza como base para implementar el objeto de "sección crítica"). Utilizado activamente en MS Windows, tanto en modo usuario como en modo kernel. Hay un objeto similar en el kernel de Linux llamado kwait_queue.
- Variables condicionales (condvars). Similares a los eventos, pero no son objetos que ocupan memoria, solo se usa la dirección de la variable, el concepto de "contenido de la variable" no existe, la dirección de un objeto arbitrario se puede usar como variable de condición. A diferencia de los eventos, establecer una variable de condición en un estado señalado no tiene consecuencias si actualmente no hay subprocesos esperando en la variable. Establecer un evento en un caso similar implica almacenar el estado "señalado" dentro del propio evento, después de lo cual los subprocesos posteriores que desean esperar el evento continúan la ejecución inmediatamente sin detenerse. Para hacer un uso completo de dicho objeto, también es necesaria la operación "liberar el mutex y esperar atómicamente la variable de condición". Utilizado activamente en sistemas operativos similares a UNIX . Las discusiones sobre las ventajas y desventajas de los eventos y las variables de condición son una parte importante de las discusiones sobre las ventajas y desventajas de Windows y UNIX.
- Puerto de terminación de E/S (IOCP). Implementado en el kernel del sistema operativo y accesible a través de llamadas al sistema, el objeto "cola" con las operaciones "poner la estructura al final de la cola" y "tomar la siguiente estructura del principio de la cola" - la última llamada suspende la ejecución del subproceso si la cola está vacía, y hasta que ningún otro subproceso realice la llamada put. La característica más importante de IOCP es que las estructuras se pueden colocar en él no solo mediante una llamada explícita al sistema desde el modo de usuario, sino también implícitamente dentro del kernel del sistema operativo como resultado de la finalización de una operación de E/S asíncrona en uno de los archivos. descriptores. Para lograr este efecto, debe utilizar la llamada al sistema "asociar un descriptor de archivo con IOCP". En este caso, la estructura colocada en la cola contiene el código de error de la operación de E/S y también, en caso de éxito de esta operación, el número de bytes realmente ingresados o emitidos. La implementación del puerto de finalización también limita la cantidad de subprocesos que se ejecutan en un solo procesador/núcleo después de recibir una estructura de la cola. El objeto es específico de MS Windows y permite el procesamiento de solicitudes de conexión entrantes y fragmentos de datos en el software del servidor en una arquitectura donde la cantidad de subprocesos puede ser menor que la cantidad de clientes (no es necesario crear un subproceso separado con costos de recursos por cada nuevo cliente).
- ERESCURSO. Un mutex que admite la captura recursiva, con semántica de captura compartida o exclusiva. Semántica: Un objeto puede ser libre, o capturado por un número arbitrario de subprocesos de manera compartida, o adquirido por un solo subproceso de manera exclusiva. Cualquier intento de realizar capturas que violen esta regla hará que el subproceso se bloquee hasta que el objeto se libere para permitir la captura. También hay operaciones del tipo TryToAcquire: nunca bloquea el hilo, lo captura o (si es necesario bloquearlo) devuelve FALSO sin hacer nada. Se usa en el kernel de Windows, especialmente en los sistemas de archivos; por ejemplo, cualquier archivo de disco abierto por alguien corresponde a la estructura FCB, en la que hay 2 objetos de este tipo para sincronizar el acceso al tamaño del archivo. Uno de ellos, el recurso de E / S de paginación, se captura exclusivamente solo en la ruta de eliminación del archivo y garantiza que, en el momento de la eliminación, el archivo no tenga E / S activas desde el caché y la asignación de memoria.
- protección deteriorada . Un objeto semidocumentado (las llamadas están en los archivos de encabezado pero no en la documentación) en el kernel de Windows. Contador con operaciones "aumentar", "disminuir" y "esperar". La espera bloquea el subproceso hasta que las operaciones de decremento reducen el contador a cero. Además, la operación de incremento puede fallar, y la presencia de un tiempo de espera actualmente activo hace que todas las operaciones de incremento fallen.
Críticas a la terminología
La traducción del término inglés thread como “thread” en un contexto relacionado con la programación contradice su traducción “thread” en un contexto de lenguaje general, y también crea colisiones con el término Data stream .
Sin embargo, el término "stream" está asociado a las traducciones de literatura técnica extranjera realizadas en la década de 1970 por la editorial Mir. Actualmente, en los "círculos académicos" (es decir, en libros de texto, medios de enseñanza, cursos universitarios, disertaciones, etc.), se considera un referente. Los términos "hilo", "hilo", etc. se consideran jerga técnica .
Véase también
Literatura
- Kunle Olukotun. Arquitectura de chip multiprocesador: técnicas para mejorar el rendimiento y la latencia. - Morgan y Claypool Publishers, 2007. - 154 p. — ISBN 159829122X . (Inglés)
- Mario Nemirovsky, Decano M. Tullsen. arquitectura multiproceso. - Morgan y Claypool Publishers, 2013. - 1608458555 p. — ISBN 1608458555 . (Inglés)
Notas
- ↑ Jeffrey Richter . "Jeffrey Richter. Windows para profesionales. Creación de aplicaciones WIN32 eficientes adaptadas a las especificaciones de Windows de 64 bits. 2001
- ↑ MSDN http://msdn.microsoft.com/en-us/library/ms682530%28VS.85%29.aspx Archivado el 23 de diciembre de 2011 en Wayback Machine .
Enlaces