Está en la página 1de 19

Programacin

Concurrente
ndice

1.

INTRODUCCIN........................................................................................................................1

2.

CONCEPTO DE PROGRAMACIN CONCURRENTE .......................................................1


2.1.
2.2.
2.3.

3.

PROGRAMA Y PROCESO .........................................................................................................1


CONCURRENCIA ....................................................................................................................2
PROGRAMACIN CONCURRENTE ...........................................................................................3

BENEFICIOS DE LA PROGRAMACIN CONCURRENTE...............................................3


3.1.
VELOCIDAD DE EJECUCIN ....................................................................................................3
3.2.
SOLUCIN DE PROBLEMAS INHERENTEMENTE CONCURRENTES .............................................3
3.2.1 Sistemas de control ..........................................................................................................3
3.2.2 Tecnologas Web..............................................................................................................4
3.2.3 Aplicaciones basadas en interfaces de usuarios..............................................................4
3.2.4 Simulacin .......................................................................................................................4
3.2.5 SGBD ...............................................................................................................................4

4.

CONCURRENCIA Y ARQUITECTURAS HARDWARE......................................................4


4.1.1
4.1.2

5.

Sistemas monoprocesador ...............................................................................................4


Sistemas multiprocesador ................................................................................................5

EJECUCIN CONCURRENTE ................................................................................................7


5.1.
QU SE PUEDE EJECUTAR CONCURRENTEMENTE? ................................................................7
5.2.
CONDICIONES DE BERNSTEIN ................................................................................................7
5.3.
ESPECIFICAR LA EJECUCIN CONCURRENTE ..........................................................................9
5.3.2 Grafos de precedencia .....................................................................................................9
5.3.3 Sentencias COBEGIN-COEND .......................................................................................9

6.

CARACTERSTICAS DE LOS SISTEMAS CONCURRENTES ........................................10


6.1.
ORDEN DE EJECUCIN DE LAS INSTRUCCIONES ....................................................................10
6.1.2 Indeterminismo ..............................................................................................................10

7.

PROBLEMAS INHERENTES A LA PROGRAMACIN CONCURRENTE....................11


7.1.
EXCLUSIN MUTUA .............................................................................................................11
7.1.2 Condicin de sincronizacin..........................................................................................12

8.

CORRECCIN DE PROGRAMAS CONCURRENTES ......................................................13


8.2.
PROPIEDADES DE SEGURIDAD ..............................................................................................14
8.3.
PROBLEMAS DE VIVACIDAD .................................................................................................14
RESUMEN ..........................................................................................................................................15

9.

EJERCICIOS ............................................................................................................................16

ndice de Figuras
Figura 2.1:
Figura 2.2:
Figura 4.1:

Programa y procesos.______________________________________________________2
Un programa dando lugar a ms de un proceso. _________________________________3
Concurrencia.____________________________________________________________5

Figura 4.2:
Figura 4.3:
Figura 4.4:
Figura 4.5:
Figura 5.1:
Figura 6.1:
Figura 6.2:
Figura 6.3:
Figura 7.1:
Figura 7.2:
Figura 7.3:
Figura 7.4:
Figura 8.1:

ii

Sistema monoprocesador con variables compartidas. _____________________________5


Paralelismo. _____________________________________________________________6
Sistema multiprocesador con memoria compartida. ______________________________6
Sistema distribuido. _______________________________________________________6
Grafo de precedencia. _____________________________________________________9
Orden total. ____________________________________________________________10
Orden parcial. __________________________________________________________10
Orden parcial: grafo de precedencia y cdigo. _________________________________10
Traza de una posible ejecucin concurrente para P1 y P2. ________________________12
Seccin crtica (1)._______________________________________________________12
Seccin crtica (2)._______________________________________________________12
Sistema compuesto por los procesos lector, gestor e impresor._____________________13
Juego del pauelo. _______________________________________________________14

Programacion Concurrente

1. Introduccin
Los primeros programas concurrentes fueron los propios Sistemas Operativos de multiprogramacin
en los que un solo procesador de gran capacidad deba repartir su tiempo entre muchos usuarios. Para
cada usuario, la sensacin era que el procesador estaba dedicado para l. Durante la dcada de los sesenta
y setenta esto fue as. La programacin de sistemas con capacidades de concurrencia se haca a bajo nivel,
en ensamblador, pues aparte de no disponer de lenguajes de alto nivel con capacidades de concurrencia,
se primaba la supuesta eficiencia del cdigo escrito directamente en ensamblador. La aparicin en 1972
del lenguaje de alto nivel Concurrent Pascal [Brinch-Hansen, 1975], desarrollado por Brinch Hansen, se
encarg de romper este mito y abrir la puerta a otros lenguajes de alto nivel que incorporaban
concurrencia.
Desde entonces la programacin concurrente ha ido ganando inters y actualmente se utiliza muy a
menudo en la implementacin de numerosos sistemas. Tres grandes hitos se nos antojan importantes para
que la programacin concurrente actualmente sea tan importante:

La aparicin del concepto de thread o hilo que hace que los programas puedan ejecutarse con
mayor velocidad comparados con aquellos que utilizan el concepto de proceso.

La aparicin ms reciente de lenguajes como Java, lenguaje orientado a objetos de propsito


general que da soporte directamente a la programacin concurrente mediante la inclusin de
primitivas especfica.

La aparicin de Internet que es un campo abonado para el desarrollo y la utilizacin de


programas concurrentes. Cualquier programa de Internet en el que podamos pensar tales como
un navegador, un chat, etc. estn programados usando tcnicas de programacin concurrente.

En lo que resta de captulo introduciremos el concepto de programacin concurrente, los beneficios


que reporta, el hardware en el que puede ejecutarse, la forma de especificarlo en un lenguaje y las
caractersticas, problemas y propiedades de correccin de un programa concurrente.

2. Concepto de programacin concurrente


Segn el diccionario de la Real Academia Espaola, una de las acepciones de la palabra concurrencia
es
Acaecimiento o concurso de varios sucesos en un mismo tiempo.
Si en esta definicin sustituimos la palabra suceso por proceso ya tenemos una primera aproximacin
a lo que va a ser la concurrencia en computacin.
Puesto que en la definicin anterior y en la que daremos posteriormente de la programacin
concurrente aparece la palabra proceso y sta est basada en el concepto de programa, se hace necesario
dejar claro en este punto qu se va a entender tanto por programa como por proceso.

2.1. Programa y proceso


Un programa es un conjunto de instrucciones. Es, simplemente, un texto que consiste en una
secuencia de lneas de cdigo que dicen qu hacer con un conjunto de datos de entrada para producir
algn tipo de salida. Se trata de algo esttico. Puede compararse con el concepto de clase en el mbito de
la programacin Orientada a Objetos (POO). Para que el programa pueda hacer algo de verdad hay que
ponerlo en ejecucin.
Una primera definicin incompleta de proceso sera la de un programa en ejecucin. Es decir, un
proceso es algo ms que las lneas de cdigo de un programa. Un proceso es algo dinmico. Est
representado por el valor del contador de programa, el contenido de los registros del procesador, una pila
y una seccin de datos que contiene variables globales. Un proceso es una entidad dinmica. Puede
compararse con el concepto de objeto en el mbito de la POO.
De igual manera que en POO puede haber mltiples objetos de una clase determinada, aqu puede
haber mltiples procesos que corresponden al mismo programa. Como ejemplo consideremos un servidor
de aplicaciones donde reside una aplicacin de navegador de Internet y existen varios usuarios ejecutando

MGB

Programacion Concurrente
ese navegador, cada uno de ellos navegando por un sitio diferente. Cada instancia del programa es un
proceso. Cada proceso tendr su propio contador de programa, as como sus propios registros, pila y
variables.
En la Figura 2.1: puede observarse el ejemplo mencionado donde existe un programa almacenado en
disco y tres instancias de ese programa ejecutndose. Son tres procesos, cada uno con su propia
informacin.

Proceso p1

Proceso p2

Proceso p3

SO

Navegador Internet

Figura 2.1:

Programa y procesos.

2.2. Concurrencia
Dos procesos sern concurrentes cuando la primera instruccin de uno de ellos se ejecuta despus de
la primera instruccin del otro y antes de la ltima. Es decir, existe un solapamiento en la ejecucin de sus
instrucciones. No tienen por qu ejecutarse exactamente al mismo tiempo, simplemente es suficiente con
el hecho de que exista un intercalado entre la ejecucin de sus instrucciones. Si se ejecutan al mismo
tiempo los dos procesos, entonces tenemos una situacin de programacin paralela. La programacin
concurrente es un paralelismo potencial. Depender del hardware subyacente como veremos ms
adelante.
De esta forma, en la figura 2.1 tendramos tres procesos concurrentes si se diese la circunstancia
anterior. Se trata de un primer nivel de concurrencia, donde existen 3 procesos independientes
ejecutndose al mismo tiempo sobre el SO. Cada proceso corresponde a una instancia de un programa.
Sin embargo, esto slo es una parte de la verdad. No necesariamente un proceso tiene por qu ser todo
el programa en ejecucin sino que puede ser parte de l. Dicho de otra forma, un programa, al ponerse en
ejecucin, puede dar lugar a ms de un proceso, cada uno de ellos ejecutando una parte del programa.
Continuando con el miso ejemplo, el programa de navegador de Internet puede dar lugar a ms de un
proceso: uno que controla las acciones del usuario con la interfaz, otro que hace las peticiones al servidor,
etc. De esta forma, la Figura 2.1 se convertira en la figura 2.2, suponiendo que se crean dos procesos
cada vez que se ejecuta el programa. Todos estos procesos tambin pueden ejecutarse concurrentemente.

MGB

Programacion Concurrente

p1.1

p1.2

p2.1

p2.2

p3.1

p3.2

SISTEMA OPERATIVO

navegador
Internet

Figura 2.2:

Un programa dando lugar a ms de un proceso.

Una definicin bastante extendida es que un proceso es un programa en ejecucin, pero no es muy
exacto pues realmente un programa puede estar compuesto por diversos procesos. Un SO no deja de ser
un programa con varios procesos que se ejecutan al mismo tiempo.
Cuando varios procesos se ejecutan concurrentemente puede haber procesos que colaboren para un
determinado fin mientras que puede haber otros que compitan por los recursos del sistema. Incluso
aquellos procesos que colaboran debern competir a la hora de obtener tiempo de procesador. Por
ejemplo, en la Figura 2.2:, p1.1 y p1.2 pueden estar colaborando para hacerle la vida ms fcil al usuario
mientras que p1.2 y p2.2 pueden estar compitiendo para acceder al disco.
Para llevar a cabo las tareas de colaboracin y competencia por los recursos se hace necesaria la
introduccin de mecanismos de comunicacin y sincronizacin entre procesos. Del estudio de estos
mecanismos trata la programacin concurrente.

2.3. Programacin concurrente


Es la disciplina que se encarga del estudio de las notaciones que permiten especificar la ejecucin
concurrente de las acciones de un programa, as como las tcnicas para resolver los problemas inherentes
a la ejecucin concurrente, que son bsicamente comunicacin y sincronizacin.
Como puede intuirse, el trabajar con procesos concurrentes va a aadir complejidad a la tarea de
programar. Cabe entonces hacerse la pregunta de cules son los beneficios que aporta la programacin
concurrente?

3. Beneficios de la programacin concurrente


Existen diversos motivos por los que la programacin concurrente es til. Destacaremos aqu dos de
ellos: velocidad de ejecucin y solucin de problemas de naturaleza concurrente. Otros beneficios
adicionales como el mejor aprovechamiento de la CPU saldrn a lo largo del captulo.

3.1. Velocidad de ejecucin


Cuando la puesta en ejecucin de un programa conlleva la creacin de varios procesos y el sistema
consta de ms de u procesador, existe la posibilidad de asignar un proceso a cada procesador de tal forma
que el programa se ejecuta de una forma ms rpida. Los programas de clculo numrico son grandes
beneficiados de este hecho.

3.2. Solucin de problemas inherentemente concurrentes


Existen algunos problemas cuya solucin es ms fcil de abordar mediante el uso de programacin
concurrente pues su naturaleza es eminentemente concurrente. Destacamos algunos de ellos, pero para
una discusin ms detallada se sugiere consultar [Bacon, 1998]

3.2.1 Sistemas de control


Son aquellos sistemas en los que hay una captura de datos, normalmente a travs de sensores, un
anlisis de esos datos y una posible actuacin posterior en funcin del resultado del anlisis. La
recoleccin de datos se puede estar haciendo de diversas entidades fsicas como por ejemplo edificios o
estancias dentro de edificios. No sera tolerable un sistema secuencial que vaya capturando los datos uno

MGB

Programacion Concurrente
a uno de las distintas estancias. Podra ocurrir que al llegar a capturar los datos de la ltima estancia, la
primera ya haya sido pasto de las llamas. Tanto la captura de datos desde cada estancia como su
tratamiento y posterior actuacin son candidatos a ser procesos distintos y de naturaleza concurrente. Esto
nos garantiza que nuestro sistema de control pueda responder a las alarmas que se produzcan.

3.2.2 Tecnologas Web


La mayora de los programas relacionados con la Web son concurrentes: los servidores Web que son
capaces de atender concurrentemente mltiples conexiones de usuarios; los programas de chat que
permiten mantener la conversacin de varios usuarios; los servidores de correo que permiten que
mltiples usuarios puedan mandar y recibir mensajes al mismo tiempo; los propios navegadores que
permiten que un usuario pueda estar haciendo una descarga mientras navega por otras pginas, o se
ejecuta un applet de Java, etc.

3.2.3 Aplicaciones basadas en interfaces de usuarios.


La concurrencia en este tipo de aplicaciones va a permitir que el usuario pueda interaccionar con la
aplicacin aunque sta est realizando alguna tarea que consume mucho tiempo de procesador. Un
proceso controla la interfaz mientras otro hace la tarea que requiere un uso intensivo de la CPU. Esto
facilitar que tareas largas puedan ser abortadas a mitad de ejecucin.

3.2.4 Simulacin
Los programas secuenciales encuentran problemas al simular sistemas en los que existen objetos
fsicos que tienen un comportamiento autnomo independiente. La programacin concurrente permitir
modelar esos objetos fsicos y ponerlos en ejecucin de forma independiente y concurrente,
sincronizndolos de la forma apropiada.

3.2.5 SGBD
En Sistemas Gestores de Bases de Datos la concurrencia juega un papel muy importante cuando se va
a permitir a varios usuarios interactuar con el sistema. Cada usuario puede ser visto como un proceso.
Obviamente hay que implementar la poltica adecuada para evitar situaciones en las que dos usuarios
modifican al mismo tiempo un registro. Sin embargo, a varios usuarios que quieran acceder a un mismo
registro para consultarlo y no modificarlo, debe permitrseles un acceso concurrente.

4. Concurrencia y arquitecturas hardware.


Parece obvio pensar que si dos procesos van a ejecutarse de forma concurrente vamos a necesitar dos
procesadores, uno para cada proceso. Sin embargo, esto no tiene por qu ser as. Depender, aunque no
exclusivamente, del hardware disponible y su topologa.
Cuando hablamos de hardware nos estamos refiriendo fundamentalmente al nmero de procesadores
en el sistema. As, se puede hacer una primera distincin entre aquellos sistemas donde slo hay un
procesador, sistema monoprocesador, y aquellos en los que hay ms de un procesador, sistemas
multiprocesador. En ambos sistemas es posible tener concurrencia.

4.1.1 Sistemas monoprocesador


Incluso en un sistema con un solo procesador podemos tener una ejecucin concurrente de procesos.
Evidentemente todos los procesos no pueden estar ejecutndose al mismo tiempo sobre el procesador,
slo uno de ellos podr estar hacindolo, pero la sensacin que le da al usuario o grupo de usuarios es la
de estar ejecutndose al mismo tiempo. Esto es debido a que el Sistema Operativo (SO) va alternando el
tiempo de procesador entre los distintos procesos. De esta forma, cuando un proceso que ocupa el
procesador en un momento determinado necesita hacer una operacin de entrada/salida, puede abandonar
el procesador para que otro proceso pueda ocuparlo y aprovechar ciclos de procesador. En la Figura 4.1:
puede verse cmo el tiempo de procesador es repartido entre tres procesos. Esta forma de gestionar los
procesos en un sistema monoprocesador recibe el nombre de multiprogramacin y es otro de los
beneficios de la programacin concurrente: un mayor aprovechamiento del procesador.
Esto es lo que ocurre en los SO que estamos acostumbrados a manejar con los ordenadores de
sobremesa tales como Windows o Linux.

MGB

Programacion Concurrente

P1
P2
P3

Figura 4.1:

Concurrencia.

Aparte de la situacin en la que un proceso puede aprovechar ciclos de CPU mientras otro proceso
hace operaciones de entrada/salida, existen otros posibles beneficios del uso de concurrencia en sistemas
monoprocesador:


La posibilidad de proporcionar un servicio interactivo a mltiples usuarios. Este sera el caso por
ejemplo de un Sistema Operativo multiusuario ejecutndose sobre una mquina monoprocesador.

La posibilidad de dar una solucin adecuada a problemas que son de naturaleza eminentemente
concurrente tal y como se mencion en la seccin 3.2.

En un sistema monoprocesador todos los procesos comparten la misma memoria. La forma de


sincronizar y comunicar procesos ser pues mediante el uso de variables compartidas. Tal y como
muestra la Figura 4.2: cuando un proceso A quiere comunicar algo a un proceso B lo deja en una variable
conocida y compartida por ambos procesos de tal forma que el proceso B lo pueda leer.

Variable
compartida

escribe

MEMORIA comn a
todos los procesos

lee

proceso
A

proceso
B

proceso
C

SISTEMA OPERATIVO

procesador

Figura 4.2:

Sistema monoprocesador con variables compartidas.

4.1.2 Sistemas multiprocesador


Un sistema multiprocesador es aquel en el que existe ms de un procesador. Esto permite que exista
un paralelismo real entre los procesos ya que idealmente cada procesador podra ejecutar un proceso. Si
tuvisemos un sistema con tres procesadores en vez de tener la Figura 4.1 el resultado podra ser el de la
4.3 en el que realmente los tres procesos se ejecutan de forma paralela.

MGB

Programacion Concurrente

P1
P2
P3

Figura 4.3:

Paralelismo.

Sin embargo, y siendo realistas, lo normal en un sistema concurrente es tener ms procesos que
procesadores por lo que, de alguna forma, tiene que haber algn esquema de multiprogramacin en uno o
ms procesadores.

Dentro de los sistemas multiprocesadores se puede hacer una pequea clasificacin:




Sistemas fuertemente acoplados: tanto los procesadores como otros dispositivos (incluida la
memoria) estn conectados a un bus. Esto permite que todos los procesadores puedan compartir la
misma memoria. Puede ocurrir que cada procesador tenga su propia memoria local, pero la
sincronizacin y comunicacin entre procesos se har mediante variables situadas en la memoria
compartida, es decir, mediante variables compartidas (4.4).

Sistemas dbilmente acoplados: aqu no existe una memoria compartida por los procesadores.
Cada procesador tiene su propia memoria local y est conectado con otros procesadores mediante
algn tipo de enlace de comunicacin. Un tipo especial de estos sistemas lo constituyen los
sistemas distribuidos, que estn formados por un conjunto de nodos distribuidos geogrficamente
y conectados de alguna forma. Estos nodos pueden ser a su vez mono o multiprocesador. El
sistema distribuido por antonomasia es Internet.

nodo
B

Variable
compartida

MEMORIA comn a
todos los procesos
paso de mensaje

escribe

lee

proceso
A

procesador

proceso
B

proceso
C

nodo
A

nodo
C

SISTEMA OPERATIVO
procesador
procesador

procesador

procesador

procesador

Figura 4.5:
Figura 4.4:

procesador

Sistema distribuido.

Sistema multiprocesador con memoria


compartida.

Suele denominarse multiproceso a la gestin de varios procesos dentro de un sistema multiprocesador


donde cada procesador puede acceder a una memoria comn y procesamiento distribuido a la gestin de
varios procesos en procesadores separados, cada uno con su memoria local.
Mientras que en los sistemas de multiproceso el esquema de la Figura 4.2: se puede seguir
manteniendo tal y como se muestra en la Figura 4.4, en el procesamiento distribuido este esquema ya no
es vlido. En un sistema distribuido la forma natural de comunicar y sincronizar procesos es mediante el

MGB

Programacion Concurrente
uso de paso de mensaje tal y como se aprecia en la Figura 4.5:. El paso de mensaje no slo es aplicable a
los sistemas distribuidos sino que tambin puede usarse en sistemas de multiproceso y de
multiprogramacin. Es por esta razn por la que actualmente los mecanismos de paso de mensaje son ms
utilizados en los lenguajes concurrentes, aparte de la buena sintona que este mecanismo guarda con la
Programacin Orientada a Objetos. No en vano, la unin de ambos paradigmas, concurrente y objetos, ha
dado lugar a lo que se conoce como Programacin Concurrente Orientada a Objetos. El lenguaje Java no
deja de ser un ejemplo.
Para terminar este apartado es bueno dejar claras algunas definiciones adicionales que a veces llevan a
confusin y en las que no todos los autores pueden estar de acuerdo:
 un programa concurrente define un conjunto de acciones que pueden ser ejecutadas
simultneamente
 un programa paralelo es un tipo de programa concurrente diseado para ejecutarse en un
sistema multiprocesador
 un programa distribuido es un tipo de programa paralelo que est diseado para ejecutarse en
un sistema distribuido, es decir, en una red de procesadores autnomos que no comparten una
memoria comn
Nos ocuparemos de los programas concurrentes, no haciendo ningn tipo de suposicin sobre el
nmero de procesadores y su topologa. Un programa concurrente debe funcionar independientemente de
que lo ejecutemos en un sistema monoprocesador o en un sistema multiprocesador, ya sea ste fuerte o
dbilmente acoplado.

5. Ejecucin concurrente
Una vez que sabemos qu es un programa concurrente y las distintas arquitecturas hardware que
pueden soportarlo, es el momento de ver qu partes de un programa se pueden ejecutar concurrentemente
y qu partes no, y cmo especificarlo en un lenguaje de programacin.

5.1. Qu se puede ejecutar concurrentemente?


Lo veremos a travs de un ejemplo. Consideramos el siguiente fragmento de programa:
x := x +1 ;
y := x +2 ;

Est claro que la primera sentencia se debe ejecutar antes de la segunda. Consideremos ahora el
siguiente fragmento:
x := 1 ;
y := 2 ;
z := 3 ;

Ahora, el orden en que se ejecuten no interviene en el resultado final. Si tuviramos tres procesadores
se podran ejecutar cada lnea en un procesador y as incrementaramos la velocidad del sistema.

5.2. Condiciones de Bernstein


Para poder determinar si dos conjuntos de instrucciones se pueden ejecutar de forma concurrente, se
definen en primer lugar los siguientes conjuntos:

L(Sk) = {a1, a2, ..an}, como el conjunto de lectura del conjunto de instrucciones Sk y que
est formado por todas las variables cuyos valores son referenciados (se leen) durante la
ejecucin de las instrucciones en Sk.

E(Sk) = {a1, a2, ..an}, como el conjunto de escritura del conjunto de instrucciones Sk y que
est formado por todas las variables cuyos valores son referenciados (se escriben) durante la
ejecucin de las instrucciones en Sk.

Para que dos conjuntos de instrucciones Si y Sj se puedan ejecutar concurrentemente, se tiene que
cumplir que:

Programacion Concurrente
1.

L( S i ) E ( S j ) =

2.

E ( S i ) L( S j ) =

3.

E (Si ) E (S j ) =

Como ejemplo supongamos que tenemos:


S1  a := x + y ;
S2  b := z 1 ;
S3  c := a b ;
S4  w := c + 1 ;

Utilizando las condiciones de Bernstein veremos qu sentencias pueden ejecutarse de forma


concurrente y cules no. Para ello, en primer lugar calculamos los conjuntos de lectura y escritura:
L(S1) ={x, y}

E(S1) = {a}

L(S2) ={z}

E(S2) = {b}

L(S3) ={a, b}

E(S3) = {c}

L(S4) ={c}

E(S4) = {w}

Ahora aplicamos las condiciones de Bernstein a cada par de sentencias:

Entre S1 y S2:

Entre S1 y S3:

L( S1 ) E ( S 2 ) =

L( S1 ) E ( S 3 ) =

E ( S1 ) L( S 2 ) =

E ( S1 ) L( S 3 ) = a

E ( S1 ) E ( S 2 ) =

E ( S1 ) E ( S 3 ) =

Entre S1 y S4:

Entre S2 y S4:

L( S1 ) E ( S 4 ) =

L( S 2 ) E ( S 4 ) =

E ( S1 ) L( S 4 ) =

E ( S 2 ) L( S 4 ) = a

E ( S1 ) E ( S 4 ) =

E(S2 ) E(S4 ) =

Entre S2 y S3:

Entre S3 y S4:

L( S 2 ) E ( S 3 ) =

L( S 3 ) E ( S 4 ) =

E ( S 2 ) L( S 3 ) = b

E ( S 3 ) L( S 4 ) = c

E (S 2 ) E(S3 ) =

E (S3 ) E (S 4 ) =

De todo esto se deduce la siguiente tabla en la que puede verse qu pares de sentencias pueden
ejecutarse de forma concurrente:

Programacion Concurrente

S1

S2
Si

S1
S2

S3

S4

No

Si

No

Si
No

S3
S4

Una vez que sabemos qu se puede y qu no se puede ejecutar concurrentemente, se hace necesario
algn tipo de notacin para especificar qu partes de un programa pueden ejecutarse concurrentemente y
qu partes no.

5.3. Especificar la ejecucin concurrente

S1

S2

S3

S4

Figura 5.1:

Grafo de precedencia.

5.3.2 Grafos de precedencia


Se trata de una notacin grfica. Es un grafo dirigido acclico. Cada nodo representar una parte
(conjunto de instrucciones) del sistema. Una flecha desde A hasta B representa que B slo puede
ejecutarse cuando A haya finalizado. Si aparecen dos nodos en paralelo querr decir que se pueden
ejecutar concurrentemente.
Para el ejemplo anterior el grafo de precedencia sera el de la figura 5.1

5.3.3 Sentencias COBEGIN-COEND


Todas aquellas acciones que puedan ejecutarse concurrentemente las introducimos dentro del par
cobegin/coend. El ejemplo anterior quedara de la siguiente forma:

begin
cobegin
a := x + y ;
b := z + 1 ;
coend
c := a b;
w := c + 1 ;
end

Programacion Concurrente
Las instrucciones dentro del par cobegin/coend pueden ejecutarse en cualquier orden, mientras que el
resto se ejecuta de manera secuencial.

6. Caractersticas de los sistemas concurrentes


La ejecucin de sistemas concurrentes tiene algunas caractersticas que los diferencian claramente de
los sistemas secuenciales. Destacamos dos:

6.1. Orden de ejecucin de las instrucciones


En los programas secuenciales hay un orden total en la ejecucin de las lneas de cdigo. Ante un
conjunto de datos de entrada se sabe siempre por dnde va a ir el programa (su flujo de ejecucin). En la
figura 6.1, por muchas veces que se ejecute el programa, el hilo de ejecucin siempre tendr el mismo
recorrido, es decir, las instrucciones siempre se ejecutarn en el mismo orden.
hilo de ejecucin

i1

i2

i2

programa

i3

i4
i5

i6

i4

i7

i5

Figura 6.1:

Orden total.

i1
i3
i6
i7

Figura 6.2:

i2
i4
i5

i1
i3
i6
i7

Orden parcial.

En los programas concurrentes, sin embargo, hay un orden parcial. Ante el mismo conjunto de datos
de entrada no se puede saber cul va a ser el flujo de ejecucin. En cada ejecucin del programa el flujo
puede ir por distinto sitio. En la figura 6.2, donde se supone que todas las instrucciones pueden ejecutarse
concurrentemente, podemos ver cmo en dos ejecuciones distintas el orden en el que se ejecutan las
instrucciones puede variar.
En la Figura 6.3 podemos observar el grafo de precedencia y el cdigo con el par cobegin/coend para
el caso de la Figura 6.2.

i1

i2

i3

i4

i5

Figura 6.3:

i6

i7

begin
cobegin
i1; i2; i3; i4; i5; i6; i7;
coend;
end.

Orden parcial: grafo de precedencia y cdigo.

6.1.2 Indeterminismo
Este orden parcial lleva a que los programas concurrentes puedan tener un comportamiento
indeterminista, es decir, puedan arrojar diferentes resultados cuando se ejecutan repetidamente sobre el
mismo conjunto de datos de entrada. Esto suele llevar a muchas sorpresas cuando uno se inicia en la
programacin concurrente.

10

Programacion Concurrente
Consideremos el siguiente programa en el que dos procesos se ejecutan concurrentemente para sumar
1 a la variable x. Esa variable x es compartida por ambos procesos pues ha sido declarada como global.
La sintaxis utilizada es la del lenguaje Pascal-FC.

program Incognita;
var x: integer;
process P1;
var i: integer;
begin
for i:=1 to 5 do x:=x+1;
end;

begin
x:=0;
cobegin
P1;
P2;
coend;
end.

process P2;
var j: integer;
begin
for j:=1 to 5 do x:=x+1
end;

Qu valor tendr la variable x al terminar el programa? Todo hace pensar que el valor debera ser 10.
Sin embargo, el valor de x puede ser 5, 6, 7, 8, 9 10.
Esta caracterstica hace muy difcil la labor de depuracin en los programas concurrentes. Podemos
ejecutar el programa 1.000 veces y podra dar como resultado 10 y al ejecutarlo 1.001 veces nos podra
dar 8.
Intuitivamente podemos ver que el error se encuentra en el acceso incontrolado a una variable
compartida por parte de 2 procesos. En la siguiente seccin vemos ms a fondo la raz del problema.

7. Problemas
concurrente

inherentes

la

programacin

Dos son bsicamente los problemas con los que nos vamos a encontrar a la hora de confeccionar un
programa concurrente: el problema de la exclusin mutua y el de la condicin de sincronizacin.

7.1. Exclusin mutua


Este problema es el que se nos da en el ejemplo anterior de los bucles. Antes de pasar a explicar el
problema hay que tener en cuenta que lo que realmente se ejecuta concurrentemente son las lneas de
cdigo generadas por el compilador. En nuestro caso, supongamos que una instruccin como x:=x+1 da
lugar a tres instrucciones de un lenguaje ensamblador cualquiera, que es lo que realmente va a ejecutar el
procesador. Tendramos los siguientes pasos:
1. Cargar desde memoria el valor de x en un registro (LOAD X R1).
2. Incrementar el valor del registro (ADD R1 1).
3. Almacenar el contenido del registro en la posicin de memoria de x (STORE R1 X).
As pues, lo que realmente se va a ejecutar de forma concurrente dentro de cada bucle es:

P1

P2

(1) LOAD X R1

(1) LOAD X R1

(2) ADD R1 1

(2) ADD R1 1

(3) STORE R1 X

(3) STORE R1 X

Cada una de estas instrucciones es atmica o indivisible, es decir, se va a ejecutar en un ciclo de reloj
del procesador sin poder ser interrumpidas. Puesto que hemos dicho que en programacin concurrente
existe un orden parcial, cualquier intercalado entre estas instrucciones es vlido. En la Figura 7.1: puede
verse una traza para un intercalado particular de estas seis lneas de cdigo en el que el valor final de la
variable x no es el esperado. Se ha perdido un incremento. Si tenemos en cuenta que estas lneas de

11

Programacion Concurrente
cdigo estn en un bucle ahora podremos entender por qu son posible resultados menores de 10 para la
variable x. Todo depender del nmero de incrementos perdidos, que en cada ejecucin puede ser distinto
e incluso no producirse.

P1

P2

3
1

Tiempo
Figura 7.1:

Traza de una posible ejecucin concurrente para P1 y P2.

En cualquier caso, el hecho de que P1 y P2 no puedan ejecutarse concurrentemente viene determinado


por las condiciones de Bernstein pues sus conjuntos de escritura no son disjuntos. El problema estriba en
que dos procesos distintos estn accediendo al mismo tiempo a una variable compartida entre los dos para
actualizarla. Nos hubiese interesado que las tres lneas de cada proceso se hubiesen ejecutado en un solo
paso, sin ningn tipo de intercalado con las otras lneas del otro proceso. A la porcin de cdigo que
queremos que se ejecute de forma indivisible se le denomina seccin crtica. Nos interesa asegurarnos
que las secciones crticas se ejecuten en exclusin mutua, es decir, slo uno de los procesos debe estar en
la seccin crtica en un instante dado. En la 7.2 puede verse cmo cuando los dos procesos llegan a la
seccin crtica slo uno de ellos podr entrar, teniendo que esperar el otro. En la Figura 7.3: puede verse
que una vez que un proceso ha salido de la seccin crtica, el otro proceso puede entrar y de esta forma
seguir ejecutndose los dos de manera concurrente.

P1

P2

x:=x+1

Figura 7.2:

P1

Seccin crtica

Seccin crtica (1).

P2

x:=x+1

Figura 7.3:

Seccin crtica

Seccin crtica (2).

La programacin concurrente deber ofrecernos mecanismos para especificar qu partes del cdigo
han de ejecutarse en exclusin mutua con otras partes.

7.1.2 Condicin de sincronizacin


Para ilustrar el problema de la condicin de sincronizacin supongamos ahora un sistema en el que
existen tres procesos (Figura 7.4:) cuyo comportamiento es el siguiente:
 lector, que va almacenando en un buffer las imgenes capturadas desde una cmara
 gestor, que va recogiendo las imgenes desde el buffer, las trata y las va colocando en una cola de
impresin
 impresor, que va imprimiendo las imgenes colocadas en la cola de impresin

12

Programacion Concurrente
cmara

impresora

LECTOR

GESTOR
buffer

Figura 7.4:

IMPRESOR
cola de impresin

Sistema compuesto por los procesos lector, gestor e impresor.

Supongamos que los tres procesos se ejecutan de manera concurrente en un bucle


infinito tal y como muestra el siguiente pseudocdigo:
process lector;

process gestor;

begin

begin

repeat

repeat

captura imagen;

coge imagen de buffer;

almacena en buffer;

trata imagen;

forever
end;

almacena imagen en cola;


forever

process impresor;
begin
repeat
coge imagen de cola;
imprime imagen;
forever
end;

end;

El lector debera apreciar que la solucin al problema est incompleta. Debera tratar de responder a
las siguientes preguntas:
 Qu ocurre cuando el proceso lector o el proceso gestor tratan de poner una imagen y el buffer o
la cola estn llenos?
 Qu ocurre cuando el proceso gestor o el proceso impresor tratan de coger una imagen y el
buffer o la cola estn vacos?

Hay situaciones en las que un recurso compartido por varios procesos, como puede ser el buffer o la
cola de impresin en nuestro ejemplo, se encuentra en un estado en el que un proceso no puede hacer una
determinada accin con l hasta que no cambie su estado. A esto se le denomina condicin de
sincronizacin.
La programacin concurrente ha de proporcionarnos mecanismos para bloquear procesos que no
puedan hacer algo en un momento determinado a la espera de algn evento (Ej. que el buffer deje de estar
vaco), pero tambin que permita desbloquearlos cuando ese evento haya ocurrido.

8. Correccin de programas concurrentes


El orden parcial e indeterminismo en la ejecucin de las instrucciones hace que la correccin de un
programa concurrente sea ms difcil de conseguir que la de un programa secuencial. Para que un
programa concurrente sea correcto, adems de cumplir las especificaciones funcionales que deba cumplir,
debe satisfacer una serie de propiedades inherentes a la concurrencia. Podemos agrupar esas propiedades
en:
 Propiedades de seguridad: son aquellas que aseguran que nada malo va a pasar durante
la ejecucin del programa.
 Propiedades de viveza: son aquellas que aseguran que algo bueno pasar eventualmente
durante la ejecucin del programa.

Para entender en qu consisten estas propiedades, consideremos el famoso juego del pauelo en el que
hay dos equipos, A y B, y un juez con un pauelo (Figura 8.1:). Cada jugador de un equipo tiene un
nmero del 1 al 3. No puede haber dos jugadores en el mismo equipo con el mismo nmero. El juez dice

13

Programacion Concurrente
un nmero y entonces los dos rivales con el mismo nmero salen corriendo a coger el pauelo. El jugador
que lo coja ha de volver corriendo a su sitio sin que su rival logre tocarle la espalda.
En este escenario explicaremos las distintas propiedades de vivacidad y seguridad.

el 2

Figura 8.1:

Juego del pauelo.

8.2. Propiedades de seguridad




Exclusin mutua. Hay recursos en el sistema que deben ser accedidos en exclusin mutua tal y
como hemos visto anteriormente. Cuando esto ocurre, hay que garantizar que si un proceso adquiere
el recurso, otros procesos debern esperar a que sea liberado. De lo contrario, el resultado puede ser
imprevisto. En nuestro ejemplo, el pauelo ha de adquirirse en exclusin mutua, o lo coge un jugador
o lo coge otro. Si lo cogen los dos a la vez puede llegar a romperse, llevando a un malfuncionamiento
del sistema.

Condicin de sincronizacin. Hay situaciones en las que un proceso debe esperar por la ocurrencia
de un evento para poder seguir ejecutndose. Cuando esto ocurre, hay que garantizar que el proceso
no prosigue hasta que no se produce el evento. De lo contrario, el resultado puede ser imprevisto. En
nuestro ejemplo, un jugador ha de esperar a que digan su nmero para poder salir corriendo. Si sale
corriendo antes llevara a un malfuncionamiento del sistema.

Interbloqueo. Se produce una situacin de interbloqueo cuando todos los procesos estn esperando
porque ocurra un evento que nunca se producir. Hay que garantizar que no se producen este tipo de
situaciones. En nuestro ejemplo se producira si un jugador se guarda el pauelo y se va para su casa.
El juez esperara porque le devolvieran el pauelo y los jugadores esperaran porque el juez dijese su
nmero, pero ninguno de estos eventos va a ocurrir nunca. Se suele conocer tambin con el nombre
de deadlock o abrazo mortal.

8.3. Problemas de vivacidad




Interbloqueo activo: El anterior interbloqueo tambin suele conocerse como pasivo. Se produce una
situacin de interbloqueo activo cuando un sistema ejecuta una serie de instrucciones sin hacer
ningn progreso. Hay que garantizar que no ocurra este tipo de situaciones. En nuestro ejemplo se
producira si dos jugadores, al intentar coger el pauelo, amagan una y otra vez, pero no se deciden a
cogerlo. Mientras que la deteccin de un intebloqueo pasivo es ms o menos simple, la deteccin de
un interbloqueo activo es muy complicada. Se suele conocer tambin con el nombre de livelock. A
partir de ahora cada vez que hablemos de interbloqueo nos referiremos al interbloqueo pasivo.

Inanicin: Se produce una situacin de este tipo cuando el sistema en su conjunto hace progresos,
pero existe un grupo de procesos que nunca progresan pues no se les otorga tiempo de procesador
para avanzar. En nuestro ejemplo podra darse si el juez nunca dice el nmero de un jugador en
concreto. Hay que garantizar que haya una cierta equidad en el trato a los procesos a no ser que las
especificaciones del sistema digan lo contrario. Se trata de un problema tambin difcil de detectar.
Su suele conocer tambin con el nombre de starvation.

14

Programacion Concurrente

Resumen
En el presente captulo se han presentado los conceptos fundamentales de la programacin
concurrente. Se ha definido el concepto de proceso, de concurrencia y de programacin concurrente. Se
han visto las distintas plataformas
hardware donde poder ejecutar programas concurrentes:
monoprocesador y multiprocesador y, en funcin de ello, se ha visto la diferencia por un lado entre
multiprogramacin, multiproceso y procesamiento distribuido y, por otro lado, entre programas
concurrentes, paralelos y distribuidos. El hecho de que dos procesos sean concurrentes no implica
necesariamente que se ejecuten exactamente al mismo tiempo. Eso depender del hardware subyacente.
En cualquier caso, e independientemente del hardware, los beneficios de la programacin concurrente
pueden resumirse en: mayor velocidad de ejecucin, mejor aprovechamiento de la CPU y soluciones
ptimas a problemas de naturaleza eminentemente concurrente.
Tambin se ha visto en este captulo cmo determinar cundo un conjunto de instrucciones puede
ejecutarse de manera concurrente mediante las condiciones de Bernstein. Una vez determinado qu se
puede ejecutar concurrentemente, hemos visto cmo especificarlo de dos formas distintas: mediante el par
cobegin/coend y mediante grafos de precedencia.
Los programas concurrentes se caracterizan por un orden parcial en la ejecucin de sus instrucciones
frente al orden total presente en los programas secuenciales. Este orden parcial nos lleva a un
indeterminismo en el resultado arrojado por la ejecucin de los programas concurrentes. Este
indeterminismo hace que la depuracin y correccin de programas concurrentes no sea una tarea
precisamente trivial.
Dos son los grandes problemas a resolver en problemas de naturaleza concurrente: el problema de la
exclusin mutua y el problema de la condicin de sincronizacin. Un programa concurrente ser correcto
si, adems de contemplar sus especificaciones funcionales donde irn implcitas condiciones de exclusin
mutua y de sincronizacin, es capaz de evitar que se produzcan situaciones de interbloqueo y de inanicin
de procesos.

15

Programacion Concurrente

9. Ejercicios
1.

Construir un programa concurrente que se corresponda con el grafo de precedencia de la


siguiente figura utilizando el par cobegin/coend

S1

S2

S3

S4

S5

S6

S7

2.

Dado el siguiente trozo de cdigo obtener su grafo de precedencia correspondiente.


s0;
cobegin
s1;
begin
s2;
cobegin
s3;s4
coend;
s5
end;
s6
coend;
s7

3.
4.

Construir un programa concurrente que explote al mximo la concurrencia para copiar un fichero
f en un fichero g utilizando el par cobegin/coend.
Usando las condiciones de Bernstein, construir el grafo de precedencia del siguiente trozo de
cdigo y el programa concurrente correspondiente usando el par cobegin/coend.
S1: cuad := x*x;
S2: m1 := a*cuad;
S3: m2 := b*x;
S4: z := m1 + m2;
S5: y := z + c;

5.

16

Construir dos programas concurrentes que se correspondan con los de la siguiente figura
utilizando el par cobegin/coend.

Programacion Concurrente

S1

S1

S2

S3

S2

S5

S4

S3

S4

S5

S6

S7
S6

Cuestiones breves
1.
2.
3.
4.
5.
6.
7.

Cul es la ventaja de la concurrencia en los sistemas monoprocesador?


Cules son las diferencias entre programacin concurrente, paralela y distribuida?
Cules son las diferencias entre multiprogramacin, multiproceso y procesamiento distribuido?
Cules son los dos problemas principales inherentes a la programacin concurrente?
Qu es una seccin crtica?
Cules son las caractersticas de un programa concurrente?
Qu se entiende por un programa concurrente correcto?

17