TEMA 4. CONCURRENCIA: EXCLUSIÓN MUTUA Y SINCRONIZACIÓN

4.1 Comunicación y sincronización de procesos

4.1.1 Cooperación entre los procesos

4.1.2 Competencia entre los procesos

4.1.3 Requisitos para la Exclusión Mutua

4.2 Utilizando memoria compartida

4.2.1 Soluciones software a la exclusión mutua

4.2.2 Soluciones hardware a la exclusión mutua

4.2.3 Semáforos

4.2.4 Monitores

4.3 Sin utilizar memoria compartida. Mensajes

4.4 Problemas Clásicos de Comunicación entre Procesos

4.4.1 La Cena de los Filósofos

4.4.2 Lectores y Escritores

4.5 Apéndice I: Arquitectura Cliente-Servidor

 

4.1 Comunicación y Sincronización de Procesos [BENA82] [LIST86] [STAL95] [TANE93] [FINK90]

Puede verse la concurrencia de procesos como la ejecución simultánea de varios procesos. Si tenemos un multiprocesador o un sistema distribuido(tema 1) la concurrencia parece clara, en un momento dado cada procesador ejecuta un proceso. Se puede ampliar el concepto de concurrencia si entendemos por procesado concurrente (o procesado paralelo) la circunstancia en la que de tomar una instantánea del sistema en conjunto, varios procesos se vean en un estado intermedio entre su estado inicial y final. Esta última definición incluye los sistemas multiprogramados de un único procesador que estudiamos en los temas anteriores.

Los distintos procesos dentro de un ordenador no actúan de forma aislada. Por un lado, algunos procesos cooperan para lograr un objetivo común. Por otro lado, los procesos compiten por el uso de unos recursos limitados, como el procesador, la memoria o los ficheros. Estas dos actividades de cooperación y competición llevan asociada la necesidad de algún tipo de comunicación entre los procesos. Parte de este tema lo dedicaremos a estudiar mecanismos de comunicación entre los procesos.

Para aclarar un poco todo esto, supongamos que en un entorno UNIX se ejecuta la orden

  cat tema1 tema2 tema3 | wc -l

 

Esta orden va a provocar que el intérprete de órdenes cree dos procesos concurrentes, el primero ejecutará el programa cat, que concatenará el contenido de los ficheros de texto tema1, tema2 y tema3. El segundo ejecutará el programa wc, que contará el número de líneas de la salida producida por cat. Estos dos procesos cooperan, y será preciso algún tipo de sincronización entre ellos, concretamente hasta que cat no produzca alguna salida wc debería bloquearse.

 

4.1.1 Cooperación entre Procesos

La velocidad de un proceso con respecto a otro es impredecible ya que depende de la frecuencia de la interrupción asociada a cada uno de ellos y cuán a menudo y de por cuánto tiempo tiene asignado cada proceso un procesador. Diremos, pues, que un proceso se ejecuta asíncronamente con respecto a otro, es decir, sus ejecuciones son independientes. Sin embargo, hay ciertos instantes en lo que los procesos deben sincronizar sus actividades. Son estos puntos a partir de los cuales un proceso no puede progresar hasta que otro haya completado algún tipo de actividad.

Los procesos también necesitan comunicarse entre sí. Por ejemplo, para leer de un fichero, los procesos de usuario deben decir al proceso que gestiona los ficheros lo que desean. Este, a su vez, debe pedirle al proceso de disco que lea los bloques necesarios. Cuando el shell conecta dos procesos con un tubo, los datos de salida del primer proceso se transfieren al segundo. Se necesita que los procesos se comuniquen entre sí, con un mecanismo bien estructurado y no por medio de interrupciones.

 

4.1.2 Competencia entre los procesos

Los recursos de un sistema pueden clasificarse como compartibles, lo que significa que pueden ser utilizados por varios procesos de forma concurrente, o no compartibles, lo que equivale a que su uso se restrinja a un sólo proceso a la vez. El hecho de que un recurso no sea compartible deriva de una de las dos razones siguientes:

 

 La naturaleza física del recurso hace que sea imposible compartirlo. Un ejemplo lo constituye una impresora, si una impresora fuera utilizada por varios procesos simultáneamente sus salidas se entremezclarían en el papel.

 El recurso es tal que si es usado por varios procesos de forma concurrente la acción de uno de ellos puede interferir con la de otro. Un ejemplo común lo constituye un fichero que contiene unos datos accesibles desde más de un proceso, y modificables al menos por uno de ellos. Por ejemplo, supongamos un fichero que contiene registros con la siguiente información sobre una cuenta bancaria:

CLAVE

SALDO

Supongamos también dos procesos que se ejecutan concurrentemente y que actualizan una misma cuenta, el proceso P1 añade al saldo el valor de la nómina y el proceso P2 descuenta del saldo una factura domiciliada. El código de los procesos es el siguiente:

 

 El resultado final de la ejecución de los dos procesos debería actualizar el saldo añadiéndole la nómina, y descontándole la factura. Sin embargo, la secuencia de ejecución en el procesador de las instrucciones a1b1b2b3a2a3, que puede darse debido a un cambio de proceso, hace que no se descuente la factura.

Dentro de la categoría de recursos no compartibles se incluirán la mayoría de los periféricos (los discos no), los ficheros de escritura y las zonas de memoria sujetas a modificación. Los recursos compartibles incluirán la CPU (en los temas previos vimos cómo compartir la CPU entre los procesos introduciendo el concepto de PCB), los ficheros de lectura, y las zonas de memoria que contengan rutinas puras o bien datos que no están sujetos a modificación.

 

4.1.3 Requisitos para la Exclusión Mutua

Los recursos no compartibles, ya sean periféricos, ficheros, o datos en memoria, pueden protegerse del acceso simultáneo por parte de varios procesos evitando que éstos ejecuten de forma concurrente sus fragmentos de código a través de los cuales llevan a cabo este acceso. Estos trozos de código reciben el nombre de secciones o regiones críticas, pudiéndose asimilar el concepto de exclusión mutua en el uso de estos recursos a la idea de exclusión mutua en la ejecución de las secciones críticas. Así, por ejemplo, puede implementarse la exclusión mutua de varios procesos en el acceso a una tabla de datos mediante el recurso de que todas las rutinas que lean o actualicen la tabla se escriban como secciones críticas, de forma que sólo pueda ejecutarse una de ellas a la vez. En el ejemplo previo de la cuenta bancaria los fragmentos de código a1a2a3 y b1b2b3 constituyen dos secciones críticas mutuamente excluyentes, esto significa que una vez que se ha comenzado la ejecución de una sección crítica, no se puede entrar en otra sección crítica mutuamente excluyente.

Idear soluciones que garanticen la exclusión mutua es uno de los problemas fundamentales de la programación concurrente. Muchas son las alternativas y tipos de mecanismos que se pueden adoptar. A lo largo de este tema veremos diferentes soluciones software y alguna hardware ; unas serán sencillas y otras complejas, algunas requieren la cooperación voluntaria de los procesos y otras que exigen un estricto ajuste a rígidos protocolos. La selección de las operaciones primitivas adecuadas para garantizar la exclusión mutua de las secciones críticas es una decisión primordial en el diseño de un sistema operativo. Al menos, una solución apropiada debería cumplir las cuatro condiciones siguientes:

 1. Que no haya en ningún momento dos procesos dentro de sus respectivas secciones críticas.

 2. Que no hagan suposiciones a priori sobre las velocidades relativas de los procesos o el número de procesadores disponibles.

 3. Que ningún proceso que esté fuera de su sección crítica pueda bloquear a otros.

  4. Que ningún proceso tenga que esperar un intervalo de tiempo arbitrariamente grande para entrar en su sección crítica.

 

ENLACE al tema anterior: PLANIFICACIÓN DE PROCESOS

ENLACE al siguiente tema: INTERBLOQUEOS

** Fin de Comunicación y Sincronización **