stringtranslate.com

Sección crítica

En la programación concurrente , los accesos simultáneos a recursos compartidos pueden dar lugar a un comportamiento inesperado o erróneo. Por lo tanto, las partes del programa en las que se accede al recurso compartido deben protegerse de forma que se evite el acceso simultáneo. Una forma de hacerlo se conoce como sección crítica o región crítica . A esta sección protegida no puede acceder más de un proceso o hilo a la vez; los demás se suspenden hasta que el primero abandona la sección crítica. Normalmente, la sección crítica accede a un recurso compartido, como una estructura de datos , un dispositivo periférico o una conexión de red, que no funcionaría correctamente en el contexto de múltiples accesos simultáneos. [1]

Necesidad de secciones críticas

Diferentes códigos o procesos pueden estar compuestos por la misma variable u otros recursos que deben leerse o escribirse, pero cuyos resultados dependen del orden en que se producen las acciones. Por ejemplo, si el proceso A debe leer una variable x y el proceso B debe escribir en la variable x al mismo tiempo, el proceso A puede obtener el valor anterior o el nuevo de x .

Diagrama de flujo que representa la necesidad de una sección crítica

Proceso A:

// Proceso A . . b = x + 5 ; // la instrucción se ejecuta en el tiempo = Tx .     

Proceso B:

// Proceso B . . x = 3 + z ; // la instrucción se ejecuta en el tiempo = Tx .     

En los casos en los que no se necesita un mecanismo de bloqueo con una granularidad más fina, es importante una sección crítica. En el caso anterior, si A necesita leer el valor actualizado de x , la ejecución del proceso A y del proceso B al mismo tiempo puede no dar los resultados requeridos. Para evitar esto, la variable x está protegida por una sección crítica. Primero, B obtiene el acceso a la sección. Una vez que B termina de escribir el valor, A obtiene el acceso a la sección crítica y se puede leer la variable x .

Al controlar cuidadosamente qué variables se modifican dentro y fuera de la sección crítica, se evita el acceso simultáneo a la variable compartida. Una sección crítica se utiliza normalmente cuando un programa multiproceso debe actualizar varias variables relacionadas sin que un subproceso independiente realice cambios conflictivos en esos datos. En una situación relacionada, una sección crítica se puede utilizar para garantizar que un recurso compartido, por ejemplo, una impresora, solo pueda ser accedido por un proceso a la vez.

Implementación de secciones críticas

La implementación de secciones críticas varía entre los diferentes sistemas operativos.

Una sección crítica normalmente terminará en un tiempo finito, [2] y un hilo, tarea o proceso debe esperar un tiempo fijo para ingresar a ella ( espera limitada ). Para garantizar el uso exclusivo de las secciones críticas, se requiere algún mecanismo de sincronización en la entrada y salida del programa.

Una sección crítica es una parte de un programa que requiere exclusión mutua de acceso.

Bloqueos y secciones críticas en múltiples subprocesos

Como se muestra en la figura [3] , en el caso de exclusión mutua ( mutex ), un subproceso bloquea una sección crítica mediante técnicas de bloqueo cuando necesita acceder al recurso compartido, y los demás subprocesos deben esperar su turno para ingresar a la sección. Esto evita conflictos cuando dos o más subprocesos comparten el mismo espacio de memoria y desean acceder a un recurso común. [2]

Pseudocódigo para implementar la sección crítica

El método más simple para evitar cualquier cambio de control del procesador dentro de la sección crítica es implementar un semáforo. En sistemas monoprocesador, esto se puede hacer deshabilitando las interrupciones al ingresar a la sección crítica, evitando llamadas al sistema que puedan causar un cambio de contexto mientras se está dentro de la sección y restaurando las interrupciones a su estado anterior al salir. Con esta implementación, cualquier hilo de ejecución que ingrese a cualquier sección crítica del sistema evitará que cualquier otro hilo, incluida una interrupción, obtenga tiempo de procesamiento en la CPU hasta que el hilo original abandone su sección crítica.

Este enfoque de fuerza bruta se puede mejorar mediante el uso de semáforos . Para ingresar a una sección crítica, un subproceso debe obtener un semáforo, que libera al salir de la sección. Se evita que otros subprocesos ingresen a la sección crítica al mismo tiempo que el subproceso original, pero son libres de obtener el control de la CPU y ejecutar otro código, incluidas otras secciones críticas que están protegidas por diferentes semáforos. El bloqueo de semáforos también tiene un límite de tiempo para evitar una condición de bloqueo en la que un solo proceso adquiere un bloqueo durante un tiempo infinito, lo que detiene a los otros procesos que necesitan usar el recurso compartido protegido por la sección crítica.

Usos de las secciones críticas

Secciones críticas a nivel de kernel

Normalmente, las secciones críticas impiden la migración de subprocesos y procesos entre procesadores y la interrupción y otros procesos y subprocesos impiden el paso de procesos y subprocesos.

Las secciones críticas suelen permitir la anidación, lo que permite entrar y salir de varias secciones críticas con un coste reducido.

Si el programador interrumpe el proceso o subproceso actual en una sección crítica, permitirá que el proceso o subproceso que se está ejecutando actualmente se ejecute hasta completar la sección crítica o programará el proceso o subproceso para otro quantum completo. El programador no migrará el proceso o subproceso a otro procesador y no programará otro proceso o subproceso para que se ejecute mientras el proceso o subproceso actual se encuentre en una sección crítica.

De manera similar, si se produce una interrupción en una sección crítica, la información de la interrupción se registra para su posterior procesamiento y la ejecución se devuelve al proceso o subproceso en la sección crítica. [4] Una vez que se sale de la sección crítica y, en algunos casos, se completa el quantum programado, se ejecutará la interrupción pendiente. El concepto de quantum de programación se aplica a las políticas de programación " round-robin " y similares .

Dado que las secciones críticas solo pueden ejecutarse en el procesador en el que se ingresan, la sincronización solo se requiere dentro del procesador en ejecución. Esto permite ingresar y salir de las secciones críticas casi sin costo. No se requiere sincronización entre procesadores. Solo se necesita la sincronización del flujo de instrucciones. [5] La mayoría de los procesadores proporcionan la cantidad necesaria de sincronización interrumpiendo el estado de ejecución actual. Esto permite que las secciones críticas en la mayoría de los casos no sean más que un recuento por procesador de secciones críticas ingresadas.

Las mejoras de rendimiento incluyen la ejecución de interrupciones pendientes a la salida de todas las secciones críticas y la posibilidad de que el programador se ejecute a la salida de todas las secciones críticas. Además, las interrupciones pendientes se pueden transferir a otros procesadores para su ejecución.

Las secciones críticas no se deben utilizar como un bloqueo primitivo de larga duración. Las secciones críticas deben ser lo suficientemente breves para que se pueda ingresar, ejecutar y salir de ellas sin que se produzcan interrupciones del hardware y del programador.

Las secciones críticas a nivel de kernel son la base del problema de bloqueo del software .

Secciones críticas en estructuras de datos

En la programación paralela, el código se divide en subprocesos. Las variables conflictivas de lectura y escritura se dividen entre subprocesos y cada subproceso tiene una copia de ellas. Las estructuras de datos como listas enlazadas , árboles y tablas hash tienen variables de datos que están enlazadas y no se pueden dividir entre subprocesos; por lo tanto, implementar el paralelismo es muy difícil. [6] Para mejorar la eficiencia de la implementación de estructuras de datos, se pueden ejecutar en paralelo múltiples operaciones como inserción, eliminación y búsqueda. Al realizar estas operaciones, puede haber escenarios en los que un subproceso busque el mismo elemento y otro lo elimine. En tales casos, la salida puede ser errónea . El subproceso que busca el elemento puede tener un acierto, mientras que el otro subproceso puede eliminarlo posteriormente. Estos escenarios causarán problemas en la ejecución del programa al proporcionar datos falsos. Para evitar esto, un método es mantener toda la estructura de datos en la sección crítica para que solo se maneje una operación a la vez. Otro método es bloquear el nodo en uso en la sección crítica, para que otras operaciones no utilicen el mismo nodo. De esta forma, el uso de la sección crítica garantiza que el código proporcione los resultados esperados. [6]

Secciones críticas en relación a los periféricos

Las secciones críticas también se producen en el código que manipula periféricos externos, como dispositivos de E/S. Los registros de un periférico deben programarse con determinados valores en una secuencia determinada. Si dos o más procesos controlan un dispositivo simultáneamente, ninguno de los procesos tendrá el dispositivo en el estado que requiere y se producirá un comportamiento incorrecto.

Cuando se debe producir una unidad compleja de información en un dispositivo de salida mediante la emisión de múltiples operaciones de salida, se requiere acceso exclusivo para que otro proceso no corrompa los datos intercalando sus propios bits de salida.

En la dirección de entrada, se requiere acceso exclusivo cuando se lee un dato complejo mediante múltiples operaciones de entrada independientes. Esto evita que otro proceso consuma algunas de las partes, lo que causaría corrupción.

Los dispositivos de almacenamiento proporcionan una forma de memoria. El concepto de secciones críticas es igualmente relevante para los dispositivos de almacenamiento como para las estructuras de datos compartidas en la memoria principal. Un proceso que realiza múltiples operaciones de acceso o actualización en un archivo está ejecutando una sección crítica que debe protegerse con un mecanismo de bloqueo de archivos adecuado.

Véase también

Referencias

  1. ^ Raynal, Michel (2012). Programación concurrente: algoritmos, principios y fundamentos . Springer Science & Business Media. pág. 9. ISBN 978-3642320279.
  2. ^ ab Jones, M. Tim (2008). Programación de aplicaciones GNU/Linux (2.ª ed.). [Hingham, Mass.] Charles River Media. pág. 264. ISBN 978-1-58450-568-6.
  3. ^ Chen, Stenstrom, Guancheng, Per (10-16 de noviembre de 2012). "Análisis de bloqueo crítico: diagnóstico de cuellos de botella en secciones críticas en aplicaciones multiproceso". Conferencia internacional de 2012 sobre computación de alto rendimiento, redes, almacenamiento y análisis . pp. 1-11. doi :10.1109/sc.2012.40. ISBN 978-1-4673-0805-2.S2CID12519578  .​{{cite book}}: CS1 maint: varios nombres: lista de autores ( enlace )
  4. ^ "ARTÍCULO DE INVESTIGACIÓN SOBRE LA SOLUCIÓN DE PROBLEMAS DE SECCIÓN CRÍTICA MEDIANTE SOFTWARE". Revista internacional de investigación en tecnología e ingeniería avanzada (IJATER) . 1 de noviembre de 2011.
  5. ^ Dubois, Scheurich, Michel, Christoph (1988). "Sincronización, coherencia y ordenamiento de eventos en multiprocesadores". Serie de encuestas y tutoriales . 21 (2): 9–21. doi :10.1109/2.15. S2CID  1749330.{{cite journal}}: CS1 maint: varios nombres: lista de autores ( enlace )
  6. ^ ab Solihin, Yan (17 de noviembre de 2015). Fundamentos de la arquitectura multinúcleo paralelo . Taylor y Francisco. ISBN 9781482211184.

Enlaces externos