stringtranslate.com

Sincronización (informática)

En informática , la sincronización es la tarea de coordinar múltiples procesos para unirse o estrecharse la mano en un punto determinado, con el fin de llegar a un acuerdo o comprometerse con una determinada secuencia de acción.

Motivación

La necesidad de sincronización no surge únicamente en sistemas multiprocesador sino en cualquier tipo de procesos concurrentes; incluso en sistemas de un solo procesador. A continuación se mencionan algunas de las principales necesidades de sincronización:

Bifurcaciones y uniones : cuando un trabajo llega a un punto de bifurcación, se divide en N subtrabajos que luego son atendidos por n tareas. Después de recibir servicio, cada subtrabajo espera hasta que todos los demás subtrabajos hayan terminado de procesarse. Luego, se vuelven a unir y salen del sistema. Por lo tanto, la programación paralela requiere sincronización ya que todos los procesos paralelos esperan a que ocurran otros procesos.

Productor-Consumidor: En una relación productor-consumidor, el proceso del consumidor depende del proceso del productor hasta que se hayan producido los datos necesarios.

Recursos de uso exclusivo: cuando varios procesos dependen de un recurso y necesitan acceder a él al mismo tiempo, el sistema operativo debe garantizar que solo un procesador acceda a él en un momento determinado. Esto reduce la concurrencia.

Requisitos

Figura 1 : Tres procesos accediendo a un recurso compartido ( sección crítica ) simultáneamente.

La sincronización de subprocesos se define como un mecanismo que garantiza que dos o más procesos o subprocesos concurrentes no ejecuten simultáneamente algún segmento de programa particular conocido como sección crítica . El acceso de los procesos a la sección crítica se controla mediante técnicas de sincronización. Cuando un hilo comienza a ejecutar la sección crítica (segmento serializado del programa), el otro hilo debe esperar hasta que finalice el primer hilo. Si no se aplican las técnicas de sincronización adecuadas [1] , se puede provocar una condición de carrera en la que los valores de las variables pueden ser impredecibles y variar según los tiempos de los cambios de contexto de los procesos o subprocesos.

Por ejemplo, supongamos que hay tres procesos, a saber, 1, 2 y 3. Los tres se están ejecutando simultáneamente y necesitan compartir un recurso común (sección crítica), como se muestra en la Figura 1. Aquí se debe utilizar la sincronización para Evite cualquier conflicto para acceder a este recurso compartido. Por lo tanto, cuando los Procesos 1 y 2 intentan acceder a ese recurso, se debe asignar solo a un proceso a la vez. Si está asignado al Proceso 1, el otro proceso (Proceso 2) debe esperar hasta que el Proceso 1 libere ese recurso (como se muestra en la Figura 2).

Figura 2 : Un proceso que accede a un recurso compartido si está disponible, basado en alguna técnica de sincronización.

Otro requisito de sincronización que debe considerarse es el orden en el que se deben ejecutar procesos o subprocesos particulares. Por ejemplo, no se puede subir a un avión antes de comprar el billete. De manera similar, no se pueden revisar los correos electrónicos antes de validar las credenciales apropiadas (por ejemplo, nombre de usuario y contraseña). Del mismo modo, un cajero automático no prestará ningún servicio hasta que reciba un PIN correcto.

Además de la exclusión mutua, la sincronización también se ocupa de lo siguiente:

Minimización

Uno de los desafíos para el diseño de algoritmos a exaescala es minimizar o reducir la sincronización. La sincronización lleva más tiempo que la computación, especialmente en la computación distribuida. La reducción de la sincronización llamó la atención de los informáticos durante décadas. Mientras que recientemente se ha convertido en un problema cada vez más importante a medida que aumenta la brecha entre la mejora de la informática y la latencia. Los experimentos han demostrado que las comunicaciones (globales) debidas a la sincronización en ordenadores distribuidos ocupan una parte predominante en un solucionador iterativo disperso. [2] Este problema está recibiendo cada vez más atención después de la aparición de una nueva métrica de referencia, el gradiente conjugado de alto rendimiento (HPCG), [3] para clasificar las 500 mejores supercomputadoras.

Problemas clásicos

Los siguientes son algunos problemas clásicos de sincronización:

Estos problemas se utilizan para probar casi todos los esquemas o primitivos de sincronización propuestos recientemente.

Sincronización de hardware

Muchos sistemas brindan soporte de hardware para códigos de secciones críticas .

Un procesador único o un sistema monoprocesador podría desactivar las interrupciones ejecutando el código que se está ejecutando actualmente sin preferencia , lo cual es muy ineficiente en sistemas multiprocesador . [4] "La capacidad clave que requerimos para implementar la sincronización en un multiprocesador es un conjunto de primitivas de hardware con la capacidad de leer y modificar atómicamente una ubicación de memoria. Sin tal capacidad, el costo de construir primitivas de sincronización básicas será demasiado alto y aumentará a medida que aumenta el número de procesadores.Existen varias formulaciones alternativas de las primitivas de hardware básicas, todas las cuales proporcionan la capacidad de leer y modificar atómicamente una ubicación, junto con alguna forma de saber si la lectura y escritura se realizaron de forma atómica. Estas primitivas de hardware son los componentes básicos que se utilizan para crear una amplia variedad de operaciones de sincronización a nivel de usuario, incluidas cosas como cerraduras y barreras . En general, los arquitectos no esperan que los usuarios empleen las primitivas de hardware básicas, sino que esperan que Los programadores de sistemas utilizarán las primitivas para construir una biblioteca de sincronización, un proceso que a menudo es complejo y complicado". [5] Muchas piezas modernas de hardware proporcionan este tipo de instrucciones atómicas, siendo dos ejemplos comunes: test-and-set , que opera en una sola palabra de memoria, y compare-and-swap , que intercambia el contenido de dos palabras de memoria.

Soporte en lenguajes de programación.

En Java , una forma de evitar interferencias de subprocesos y errores de coherencia de la memoria es anteponer la firma de un método con la palabra clave sincronizada , en cuyo caso el bloqueo del objeto declarante se utiliza para imponer la sincronización. Una segunda forma es envolver un bloque de código en una sección sincronizada(algúnObjeto){...} , que ofrece un control más detallado. Esto obliga a cualquier hilo a adquirir el bloqueo de algún Objeto antes de que pueda ejecutar el bloque contenido. El bloqueo se libera automáticamente cuando el hilo que adquirió el bloqueo abandona este bloque o entra en un estado de espera dentro del bloque. Cualquier actualización de variables realizada por un subproceso en un bloque sincronizado se vuelve visible para otros subprocesos cuando adquieren de manera similar el bloqueo y ejecutan el bloque. Para cualquier implementación, se puede utilizar cualquier objeto para proporcionar un bloqueo porque todos los objetos Java tienen un bloqueo intrínseco o un bloqueo de monitor asociado a ellos cuando se crean instancias. [6]

Los bloques sincronizados de Java , además de permitir la exclusión mutua y la coherencia de la memoria, permiten la señalización, es decir, enviar eventos desde los subprocesos que han adquirido el bloqueo y están ejecutando el bloque de código a aquellos que están esperando el bloqueo dentro del bloque. Por lo tanto, las secciones sincronizadas de Java combinan la funcionalidad de mutexes y eventos para garantizar la sincronización. Esta construcción se conoce como monitor de sincronización .

.NET Framework también utiliza primitivas de sincronización. [7] "La sincronización está diseñada para ser cooperativa, exigiendo que cada subproceso siga el mecanismo de sincronización antes de acceder a recursos protegidos para obtener resultados consistentes. El bloqueo, la señalización, los tipos de sincronización livianos, el spinwait y las operaciones entrelazadas son mecanismos relacionados con la sincronización en .NET". [8]

Muchos lenguajes de programación admiten la sincronización y se han escrito lenguajes especializados completos para el desarrollo de aplicaciones integradas donde la sincronización estrictamente determinista es primordial.

Implementación

bloqueo de giro

Otra forma eficaz de implementar la sincronización es mediante el uso de spinlocks. Antes de acceder a cualquier recurso compartido o fragmento de código, cada procesador verifica una bandera. Si se restablece el indicador, entonces el procesador establece el indicador y continúa ejecutando el hilo. Pero, si la bandera está configurada (bloqueada), los hilos seguirán girando en un bucle y seguirán verificando si la bandera está configurada o no. Sin embargo, los spinlocks son efectivos solo si el indicador se restablece para ciclos más bajos, de lo contrario, puede provocar problemas de rendimiento, ya que desperdicia muchos ciclos de procesador en espera. [9]

Barreras

Las barreras son fáciles de implementar y proporcionan una buena capacidad de respuesta. Se basan en el concepto de implementar ciclos de espera para proporcionar sincronización. Considere tres subprocesos ejecutándose simultáneamente, comenzando desde la barrera 1. Después del tiempo t, el subproceso1 alcanza la barrera 2 pero aún tiene que esperar a que los subprocesos 2 y 3 alcancen la barrera2 ya que no tiene los datos correctos. Una vez que todos los hilos alcanzan la barrera 2, todos comienzan de nuevo. Después del tiempo t, el hilo 1 alcanza la barrera 3 pero tendrá que esperar a los hilos 2 y 3 y a los datos correctos nuevamente.

Por lo tanto, en la sincronización de barrera de múltiples subprocesos siempre habrá algunos subprocesos que terminarán esperando a otros subprocesos, como en el ejemplo anterior, el subproceso 1 sigue esperando a los subprocesos 2 y 3. Esto da como resultado una degradación grave del rendimiento del proceso. [10]

La función de espera de sincronización de barrera para el i -ésimo subproceso se puede representar como:

(Wbarrera)i=f ((Tbarrera)i, (Rhilo)i)

Donde Wbarrier es el tiempo de espera de un subproceso, Tbarrier es la cantidad de subprocesos que han llegado y Rthread es la tasa de llegada de subprocesos. [11]

Los experimentos muestran que el 34% del tiempo total de ejecución se dedica a esperar otros subprocesos más lentos. [10]

Semáforos

Los semáforos son mecanismos de señalización que pueden permitir que uno o más subprocesos/procesadores accedan a una sección. Un semáforo tiene una bandera que tiene un cierto valor fijo asociado y cada vez que un hilo desea acceder a la sección, disminuye la bandera. De manera similar, cuando el hilo abandona la sección, la bandera se incrementa. Si la bandera es cero, el hilo no puede acceder a la sección y se bloquea si decide esperar.

Algunos semáforos permitirían sólo un hilo o proceso en la sección de código. Estos semáforos se denominan semáforos binarios y son muy similares al Mutex. Aquí, si el valor del semáforo es 1, se permite el acceso al hilo y si el valor es 0, se deniega el acceso. [12]

Fundamentos matemáticos

La sincronización era originalmente un concepto basado en procesos mediante el cual se podía obtener un bloqueo en un objeto. Su uso principal fue en bases de datos. Hay dos tipos de bloqueo (de archivo) ; sólo lectura y lectura-escritura. Muchos procesos o subprocesos pueden obtener bloqueos de solo lectura. Los bloqueos de lector-escritor son exclusivos, ya que solo pueden ser utilizados por un único proceso/hilo a la vez.

Aunque los bloqueos se derivaron para bases de datos de archivos, los datos también se comparten en la memoria entre procesos y subprocesos. A veces se bloquea más de un objeto (o archivo) a la vez. Si no están bloqueados simultáneamente, pueden superponerse, provocando una excepción de interbloqueo.

Java y Ada solo tienen bloqueos exclusivos porque se basan en subprocesos y dependen de la instrucción del procesador de comparación e intercambio .

El monoide histórico proporciona una base matemática abstracta para las primitivas de sincronización . También hay muchos dispositivos teóricos de nivel superior, como cálculos de proceso y redes de Petri , que se pueden construir sobre el monoide histórico.

Ejemplos

A continuación se muestran algunos ejemplos de sincronización con respecto a diferentes plataformas. [13]

En Windows

Windows proporciona:

En Linux

Linux proporciona:

La activación y desactivación de la preferencia del kernel reemplazó los bloqueos de giro en los sistemas monoprocesador. Antes de la versión 2.6 del kernel, Linux deshabilitaba la interrupción para implementar secciones críticas breves. Desde la versión 2.6 y posteriores, Linux es totalmente preventivo.

En Solaris

Solaris proporciona:

En Pthreads

Pthreads es una API independiente de la plataforma que proporciona:

Ver también

Referencias

  1. ^ Gramoli, V. (2015). Más de lo que nunca quiso saber sobre la sincronización: Synchrobench, que mide el impacto de la sincronización en algoritmos concurrentes (PDF) . Actas del 20º Simposio ACM SIGPLAN sobre principios y práctica de la programación paralela. ACM. págs. 1–10.
  2. ^ Shengxin, Zhu y Tongxiang Gu y Xingping Liu (2014). "Minimizar las sincronizaciones en solucionadores iterativos dispersos para supercomputadoras distribuidas". Computadoras y Matemáticas con Aplicaciones . 67 (1): 199–209. doi : 10.1016/j.camwa.2013.11.008 .
  3. ^ "Parámetro de referencia HPCG".
  4. ^ Silberschatz, Abraham; Gagne, Greg; Galvin, Peter Baer (11 de julio de 2008). "Capítulo 6: Sincronización de procesos". Conceptos de sistemas operativos (Octava ed.). John Wiley e hijos. ISBN 978-0-470-12872-5.
  5. ^ Hennessy, John L.; Patterson, David A. (30 de septiembre de 2011). "Capítulo 5: Paralelismo a nivel de subproceso". Arquitectura informática: un enfoque cuantitativo (Quinta ed.). Morgan Kaufman. ISBN 978-0-123-83872-8.
  6. ^ "Bloqueos intrínsecos y sincronización". Los tutoriales de Java . Oráculo . Consultado el 10 de noviembre de 2023 .
  7. ^ "Descripción general de las primitivas de sincronización". Microsoft aprende . Microsoft . Consultado el 10 de noviembre de 2023 .
  8. ^ Despertar, Margarita. "Sincronización". Techinfo . Consultado el 10 de noviembre de 2023 .
  9. ^ Massa, Antonio (2003). Desarrollo de Software Embebido con ECos . Pearson Education Inc. ISBN 0-13-035473-2.
  10. ^ ab Meng, Chen, Pan, Yao, Wu, Jinglei, Tianzhou, Ping, Jun. Minghui (2014). "Un mecanismo especulativo para la sincronización de barreras". Conferencia internacional IEEE de 2014 sobre informática y comunicaciones de alto rendimiento (HPCC), Sexto Simposio internacional de IEEE sobre seguridad en el ciberespacio (CSS) de 2014 y 11.ª Conferencia internacional de IEEE sobre software y sistemas integrados (ICESS) de 2014 .{{cite journal}}: Mantenimiento CS1: varios nombres: lista de autores ( enlace )
  11. ^ Rahman, Mohammed Mahmudur (2012). "Sincronización de procesos en multiprocesador y procesador multinúcleo". 2012 Conferencia Internacional sobre Informática, Electrónica y Visión (ICIEV) . págs. 554–559. doi :10.1109/ICIEV.2012.6317471. ISBN 978-1-4673-1154-0. S2CID  8134329.
  12. ^ Li, Yao, Qing, Carolyn (2003). Conceptos en tiempo real para sistemas integrados . Libros CMP. ISBN 978-1578201242.{{cite book}}: Mantenimiento CS1: varios nombres: lista de autores ( enlace )
  13. ^ Silberschatz, Abraham; Gagne, Greg; Galvin, Peter Baer (7 de diciembre de 2012). "Capítulo 5: Sincronización de procesos". Conceptos de sistemas operativos (Novena ed.). John Wiley e hijos. ISBN 978-1-118-06333-0.
  14. ^ "¿Qué es RCU, fundamentalmente? [LWN.net]". lwn.net .
  15. ^ "Sondas de bloqueo adaptativas". Documentos de Oracle .
  16. ^ Mauro, Jim. "Torniquetes y herencia prioritaria - SunWorld - Agosto de 1999". sunsite.uakom.sk .

enlaces externos