Beruflich Dokumente
Kultur Dokumente
REPASO DE CONCEPTOS
3.9 Cuando el valor asociado a un semáforo solo puede tomar dos valores (verdadero
o falso), entonces decimos que se trata de un semáforo__________________
3.11 La variante del problema de tos lectores y escritores que exige que no se
mantenga esperando ningún lector a menos que un escritor ya haya obtenido
permiso para usar el objeto compartido se denomina____________________
3.12 La variante del problema de los lectores y escritores que exige que ningún lector
nuevo pueda comenzar a leer si un escritor está esperando para acceder al objeto se
denomina_____________
3.14 La herramienta de sincronización posee entre sus operaciones una que provoca
el bloqueo incondicional del proceso que la invoca.
3.15 La construcción lingüística de alto nivel que garantiza exclusión mutua por
definición y -que permite además establecer una condición de entrada a la sección
crítica que es gestionada por la propia herramienta se denomina________________
3.16 Cuando una operación signal sobre una variable condición despierta a un
proceso bloqueado por haber realizado una operación wait sobre la variable
condición y a su vez bloquea al proceso que invoca dicha operación signal, entonces
estamos ante una variable condición que funciona según el
estilo___________________________
3.17 Cuando una operación signal sobre una variable condición hace que compitan
juntos tanto un proceso despertado por dicha operación (bloqueado por haber
ejecutado previamente una operación wait) como los procesos que quieren entrar en
el monitor, entonces estamos ante una variable condición que funciona según el
estilo
TESTS
a) los semáforos
d) los monitores
3.19 Las regiones críticas pueden resolver más problemas de sincronización que los
semáforos
a) verdadero
b) falso
a) El proceso que ejecuta la operación se bloquea hasta que otro ejecute una
operación signal o
3.22 para resolver el problema de la exclusión mutua, puede emplearse una variable
global turno con el identificador del proceso que tiene derecho a entrar en la sección
crítica. Cada vez que un proceso sale de su SC, cambia el valor de turno al
identificador de otro proceso. Esta solución
a) es correcta
c) monitores
a) Sí
c) No
c) a) y b) son ciertas
CUESTIONES Y EJERCICIOS
//Variables globales
const int N=...
bool eleccion[N];
int numero[N];
Codigo del Proceso Pk {
int j;
while (true) {
//Inicio de la sección de entrada
eleccion[k]=true;
numero[k]=min(numero[0],numero[1]..., numero[n-1])+1;
eleccion[k]=false;
for(j=0;j<N;j++) {
while (eleccion[j]) no-operar;
while (numero[j]!=0 && ((numero([j],j)<(numero[k],k)) no-operar;
}
//Final de la seccion de entrada
Seccion critica
//Inicio de la seccion de salida
numero[k] := 0;
//Final de la seccion de salida
Seccion restante
}
Siendo:
mín (v0, vl , , va): función que devuelve el valor mínimo (a, b) < (c, d): devuelve true
si se cumple a < c o ((a = c) y (b < d)), en caso contrario devuelve false;
3.34 ¿Por qué las soluciones al problema de la sección crítica para más de dos
procesos son bastante más complicadas que las soluciones para solo dos procesos
concurrentes?
3.35 Los sistemas operativos actuales disponen de llamadas al sistema para bloquear
el acceso a un archivo. Si un proceso bloquea un archivo, por ejemplo, lock(fichero),
cualquier otro proceso que pretenda acceder al archivo queda bloqueado; este
bloqueo ocurre con cualquier llamada al sistema que implique un acceso al archivo
(incluida la lock). El bloqueo se mantiene hasta que el proceso que retiene el archivo
invoca una operación de desbloqueo (por ejemplo, unlock(fichero)).
a) Ilustre con un ejemplo real la conveniencia de estos servicios de bloqueo y
desbloqueo.
3.38 ¿Por qué son necesarias las variables de tipo condición en los monitores?
3.41 Enumere las ventajas e inconvenientes que tienen los monitores sobre las
regiones críticas.
PROBLEMAS
3.45 Construya un monitor que gestione una comunicación sencilla entre procesos
mediante dos primitivas de envío y recepción de mensajes, cumpliendo estas
especificaciones:
Para las transacciones existe un tipo de datos llamado mensaje que se supone
ya definido. Los procesos participantes en la comunicación poseerán
identificadores enteros positivos. Existe un máximo de procesos dialogantes,
llamémoslo num_proc (que es constante).
El monitor contendrá un búfer de M ranuras (M será alguna constante) de
tipo mensaje.
Como repositorio de transacciones pendientes. Podrán definirse estructuras y
variables adicionales, pero ninguna más de tipo mensaje.
El monitor ofrecerá dos procedimientos públicos con esta sintaxis:
enviar ( var m:mensaje, destino : intege, quien_soy: integer ) ;
recibir ( var m: mensaje, quien_soy : integer ) ;
El parámetro destino del procedimiento enviar indica a qué proceso se desea
emitir el mensajero.
El parámetro quien_soy de recibir expresa qué proceso está demandando
mensajes.
El procedimiento enviar deposita el mensaje en en el búfer y lo deja
disponible para su consumo; si el búfer está lleno el proceso llamador se
bloquea hasta que haya hueco.
Si se produce el bloqueo no se impide a otros procesos utilizar el monitor
(que quizás vacíen el búfer).
El procedimiento recibir bloqueará al proceso llamador hasta que exista
algún mensaje destinado a tal proceso. Este bloqueo no impedirá a otros
procesos utilizar el monitor si están capacitados para ello. Si existe al menos
un mensaje destinado al invocante de recibir, en el parámetro m se copia el
mensaje llegado en primer lugar de todos los posibles, y se elimina del búfer
del monitor (un mensaje solo ge recibe una vez).
Inicialmente el monitor no contiene mensajes.
3.47 Desarrolle una solución al problema de los lectores y escritores con prioridad
para los procesos escritores empleando:
a) Semáforos
b) RCC
c) Monitores
3.49 En una tienda de pájaros están teniendo problemas para tener a todos sus
canarios felices. Los canarios comparten una jaula en la que hay un plato con alpiste
y un columpio para hacer ejercicio. Todos los canarios quieren inicialmente comer
del plato y después, columpiarse. Pero se encuentran con el inconveniente de que
solo tres de ellos pueden comer del plato al mismo tiempo y solo uno puede
columpiarse. Defina un proceso que ejecuten los canarios concurrente-mente de
forma que sincronicen sus actividades empleando:
a) Semáforos
b) RCC
e) Monitores
3.50 Diseñe una solución al primer problema de los lectores y escritores (prioridad
para los lectores), añadiendo el requisito de que no puede haber más de 20 lectores
simultáneos. La solución consistirá en el código que ha de ejecutar un proceso lector,
y el que ha de ejecutar un proceso escritor. Desarrolle una solución empleando:
a) Semáforos
b) RCC
e) Monitores
El comportamiento de los clientes y del servidor debe cumplir las siguientes reglas:
4. Como máximo solo puede haber 10 clientes esperando por ser servidos. (Si un
cliente intenta pedir servicio habiendo ya otros diez clientes en cola, no se realiza la
petición.)
a) Semáforos
b) RCC
e) Monitores
3.53 Para cada una de las siguientes descripciones de funcionamiento de las variables
tipo condición, realice una implementación del tipo monitor utilizando semáforos:
a) Cuando un proceso realiza un signal, entonces sale inmediatamente del monitor;
si hay procesos detenidos por haber realizado anteriormente un wait, se producirá la
reanudación de uno de ellos. h) Cuando un proceso realiza un wait, entonces se
bloquea hasta que otro proceso, después de haber realizado un signal, sale del
monitor o bien se bloquea al realizar un wait.
3.54 En cierto sistema concurrente, cada proceso tiene asignado un peso W (es un
entero positivo). Los procesos acceden a un archivo compartido, pudiendo trabajar
concurrentemente con él, pero con la restricción de que la suma total de los pesos de
los procesos que actualmente están trabajando con el archivo tiene que mantenerse
por debajo de cierto límite W.
a) Semáforos
b) RCC
c) Monitores
SOLUCIONES
Repaso de conceptos
3.2. Progreso
3.3. Progreso
3.5. Test_and_Set
3.6 Swap
3.7. P
3.8. V
3.9. Binario
TESTS
3.18. d
3.19. b
3.20. b
3.21. c
3.22. c
3.23. d
3.24. c
3.25. d
3.26. c
3.27. a
3.28. a
3.29. c
CUESTIONES
3.30 Todo monitor es un tipo abstracto de datos o sea, entidades que definen datos y
métodos para manipularlos. Difieren en que el monitor garantiza por definición
exclusión mutua en todos sus métodos y funciones, es decir, desde que un proceso
invoque a un método del monitor y se encuentre ejecutando sus instrucciones,
cualquier otro proceso que intente acceder al mismo (bien a través de la misma
función miembro o a través de cualquier otra) quedará bloqueado a la espera de que
el proceso que se encuentra ejecutando uno de los métodos del monitor lo
abandone.
3.31 Para comprobar que el algoritmo es correcto, hay que demostrar que cumple las
tres condiciones de exclusión mutua, progreso y espera limitada.
Puede comprobarse que cuando el proceso calcula su número [k] a partir del
mínimo de los valores de numero E, se devolverá siempre un uno. Esto ocurre
porque el mínimo encontrado siempre es cero, que es el valor que precisamente tenía
numero [1(] antes de empezar a buscar el mínimo.
Lo anterior significa que los valores de número [k] solo pueden ser:
— uno (el proceso quiere entrar en sección crítica). A su vez, eso significa que la
línea
while (numero [j]1.0 && (numero ( [j],j)< (numero [k] ,k) ) no-operar;
realmente es equivalente a:
O sea, que un proceso K espera por otro proceso J si y solo si el proceso J quiere
entrar en sección crítica y el identificador de J es menor que el de K. Esto significa
que si el proceso 10 está dentro de la sección crítica y el proceso 5 está interesado en
entrar, este último NO esperará por el proceso 10 y entrará sin más en sección
crítica. Es más, si llega el proceso 3, también entrará en sección crítica, porque no
esperará ni por el 5 ni por el 10. Por tanto, se viola flagrantemente el requisito de
exclusión mutua.
Proceso 0. Proceso 1.
eleccion[0]=true eleccion[1]=true
numero[0]=1 numero[1]=1
eleccion[0]=false eleccion[1]=false
numero[0]=0 numero[1]=0
Puede verse que el proceso O no tiene en cuenta al proceso 1 para entrar en sección
crítica (solo se podría bloquear brevemente mientras eleccion [ 1 ] sea cierto, cosa
que solo ocurre fugazmente, mientras el proceso 1 está lijando el valor de numero
[11). En otras palabras, el proceso O entra en la sección crítica cuando quiere, incluso
si el proceso 1 está dentro.
Progreso. Sí la cumple ya que, por un lado, solo los que quieren entrar en la sección
crítica influyen en la elección de quién entra (tendrán sus elementos de número
asociados a va-lores distinto de cero), y por otro lado, la elección siempre se realiza
en un tiempo finito (en caso de existir varios con un mismo valor de número,
entonces entra el que posea un menor identificador de proceso).
Espera limitada. No la cumple ya que existe la posibilidad de que varios procesos
posean un mismo valor de número debido a la fórmula empleada para su obtención
(que no tiene en cuenta el orden de petición). De hecho, los únicos valores de
número son 0 o 1. Si esto ocurriese siempre entraría aquél con un identificador
menor, por tanto, se podría producir un "castigo" a aquellos procesos que posean
identificadores mayores.
3.35 Solución:
3.37 Los semáforos son tan solo una herramienta para la sincronización de procesos
concurrentes. No resuelven por sí solos ningún problema de gestión de recursos
como el interbloqueo o la inanición.
3.38 Para que un proceso dentro de un monitor pueda esperar por un evento sin que
acapare el uso del monitor y sin necesidad de recurrir a semáforos u otras
construcciones.
3.39 Porque trata de que solo un proceso dentro de un grupo pueda ejecutar código
de sección crítica; por tanto los restantes procesos han de esperar y el grupo ha de
sincronizarse.
3.41 Ventajas de los monitores clásicos sobre las regiones críticas condicionales: Los
monitores no permiten construir regiones críticas en cualquier punto del programa,
ya que todos los accesos a los datos están encapsulados como operaciones públicas
del monitor. Esto genera dos ventajas:
Problemas
class Planificador {
private:
int proceso:
bool ocupado: //Indica si el recurso esta asignado o no.
Lock *llave;
Condition *turno; // vinculada al cerrojo "Llave"
int Nespera; //Indica cuantos procesos esperan por el recurso public:
void planificador() {
llave = new(Lock);
turno = new(condition):
ocupado = false;
proceso = -1;
Nespera = O;
);
void planificador() {
assert(ocupado == false);
assert(Nespera == O)
delete llave;
delete turno; };
int pido_recurso( int pid ) {
int retorno;
llave.acquire();
if ((ocupado== true) && (proceso==pid) ) {
retorno = -1
else {
if (ocupado== true) {
nespera = Nespera + 1;
turno.wait(): Nespera = Nespera - 1;
ocupado = true;
proceso = pid;
retorno = O;
llave.
Release();
return(retorn0):
} ;
int libero_recurso( int pid ) {
int retorno;
Llave.acquire () ;
if ((Ocupado = falso) H (Proceso = pid) ) {
retorno = -1;
else {
Ocupado = false; if ( Nespera > O )
Turno.signal()
llave.release();
Return (retorno);
};
}:
3.45 Solución:
Monitor Buzon
{
mensaje buffer[M];
int destinatario[M], mensajes_pendientes[num_proc];
int inserto[num_proc], extraigo[num_proc], nhuecos;
ínt nhuecos;
Condition hay_hueco, hay_mensaje[num_proc];
void Buzon() {
for ( i = 0 ; i < num_proc; i++) {
extraigo[i] = O;
inserto[i] = O;
mensajes_pendientes[destino] = O;
destino[i] = -1;
}
nhuecos = M;
};
void enviar (mensaje m, int destino, int quien_soy)
{
integer k;
if ( nhuecos == O ) {
hay_hueco.wait;
k = inserto[quien_soy]%M;
nhuecos--;
buffer [k] =m;
destinatario[k] = destino;
inserto{quien_soy}= (k+l)%M;
mensajes_pendientes[destino)++
,hay_mensajes[destino].signal;
};
Void recibir (mensajes m, int quien_soy)
{
Integer k;
If (hay_mensaje[quien_soy].wait;
}
K=extraigo(quien_soy);
do{
if destino[k] == quien_soy )
m = buffer[k];
destino[k] = -1;
extraigo[quien_soy] = (k+l)%M;
nhuecos++;
mensajes_pendientes[destino]--;
return;
else {
k = (k+l) %M;
}
while ( k != extraigo[quien_soy] );
return; );
};
};
El motivo de que los receptores deben tener mayor prioridad se debe a que de esta
forma se intenta evitar la saturación del búfer de mensajes. Se puede producir
interbloqueo entre dos procesos que esperan mutuamente por mensajes enviados
por el otro proceso.
No se produce inanición debido a que los procesos entran por orden de llegada y se
salen del estado de bloqueo, variables condición, también por orden.
3.46 Solución:
Semaphore sem(0) ;
Proceso A:
... instrucciones de A...
sem.V();
Proceso B:
... instrucciones de B...
sem.V();
Proceso C:
sem-P();
... instrucciones de C...
Comentario: cuando el primero de los procesos A o B finalice, hace una operación V
sobre el semáforo, con lo cual permite a C ejecutarse. La segunda operación V no
provoca ningún efecto en C, incluso aunque suceda antes de que C ejecute la
operación P.
3.47 Solución:
a) Semáforos
Variables globales
Semaphore mutex (1) , lector ( O ) , escritor (0) :
int n1=0, nle=0, nee=0;
bool escribiendo=false;
Codigo del proceso Lector {
…
mutex.P();
if (escribiendo I I nee>0) {
nle++;
mutex.V();
lector.P();
nle++;
if (nle>0)
lector .v( ) ;
else mutex.V ( ) ;
LEER DEL RECURSO
mutex.P();
nl--;
if (n1==0 && nee>0)
escritor.V();
else mutex.V();
…
}
Codigo del proceso Escritor {
…
mutex.P();
if (nl>0 II escribiendo) {
nee++;
mutex.V();
escritor-P();
nee--;
);
escribiendo=true;
mutex.V();
ESCRIBIR EN EL RECURSO
mutex.P();
ne--;
if (nee>0)
escritor.V();
else if (nle>0)
lector...V();
else mutex_V();
…
}
b)RCC
Variables globales
Shared lect_esc {
int n1=0, nee=0;
bool escribiendo=false;
);
Codigo del proceso Lector {
…
region lect_esc when (!escribiendo && nee==0) {
n1++;
}
LEER DEL RECURSO
region lect_esc {
nl--;
}
…
}
Codigo del proceso Escritor {
…
region lect_esc
nee++ region
lect_esc when (n1==0 && !escribiendo) {
escribiendo=true;
nee--;
ESCRIBIR EN EL RECURSO
region lect_esc { escribiendo=false;
}
…
}
c) Monitores
Variables globales
Monitor Lectores_Escritores {
int nl, nle, nee;
bool escribiendo;
Condition lector, escritor;
public void Empezar_Lectura() {
if (escribiendo or nee>0) {
nle++ ;
lector _wait O ;
nle--;
nl++; lector .signal();
public void Terminar_Lectura() {
nl--;
if (n1==0)
escritor .signal() ;
}
public void Empezar_ Escritura() {
if (nl! =O 1 1 escribiendo) { nee++ ;
escritor.wait();
nee--;
escribiendo=true;;
}
public void Terminar_Escritura()
escribiendo= false ;
if (nee>0) escritor. signal () ;
else lector.signal();
}
public Lectores_Escritores() {
nl=n1e=nee=0;
escribiendo=false;
; Monitor Lectores_Escritores Lect_Esc;
Codigo del proceso Lector {
…
Lect_Esc.Empezar_Lectura();
LEER DEL RECURSO
Lect_Esc.Terminar_Lectura();
Codigo del proceso Escritor
…
{ Lect_Esc.Empezar_Escritura();
ESCRIBIR EN EL RECURSO
Lect_Esc.Terminar_Escritura();
…
}
}
3.48 Solución:
Notas previas:
Se supone que una operación V sobre un semáforo que ya tiene el valor 1 deja
inalterado el semáforo.
La implementación funciona con cualquier semántica de variables condición
(Mesa, Hoa-re, etc.).
monitor BinarySemaphore {
private boolean available;
private Condition queue;
public BinarySemaphore (boolean initialValue)
available = initiaivalue;
public void P () {
while ( ! available ) {
queue.wait ( );
available = false;
}
public void V O {
available = true;
queue.signal();
3.49 Solució n:
a) Semáforos
Semaphore alpiste (3);
Semaphore columpio (1);
void Canario ()
{
alpiste.P();
... comer ...
alpiste.V();
columpio.P();
...columpiarse ... columpio.V();
}
b) RCC
shared Alpiste int comiendo=0;
shared Columpio boolean columpio_libre = true;
void canario ()
region Alpiste when comiendo<3
comiendo++;
…comer…
region Alpiste comiendo--;
region Columpio when columpio_libre
columbio_libre = false;
…columpiarse…
region columpio columpio_libre = true;
c) Monitores
monitor Comedor
{
private int comiendo;
prívate Condition cola_comer;
public Comedor(){
comiendo = O;
}
public void Empieza() {
while ( comiendo == 3 ) {
cola_comer.wait();
} comiendo++;
}
public void Termina() {
comiendo--;
cola_comer.signal();
}
}
monitor Columpio
{
private boolean columpio_libre;
private Condition cola_columpio;
public Columpio() {
columpio_libre = true;
}
public void Empieza() {
while ( ! columpio_libre){
cola_columpio.wait();
}
Public void Empieza () {
While columpio_libre = false;
Cola_columpio.wait();
}
public void Termina() {
columpio_libre = true;
cola_columpiarse.signal();
}
void Canario ()
Comedor.Empieza();
... comer ...
Comedor.Termina();
... columpiarse ...
Columpio.termina();
}
3.50 Solución:
a) Semá foros
Class Lectores_Escritores {
prívate:
semaphore esch(1) mutex (1) , lect (20) ;
int cuentalect;
public:
void escritor() {
esch.P();
…
Se realiza escritura
…
esch.V();
) ;
void lector(){
lect.P();
mutex.P()
cuentalect++
if ( cuentalect == 1 ) {
esch . P ()
}
mutex.V1();
Se realiza la lectura;
mutex.P();
cuentalect--;
if ( cuentalect == 0 ) {
esch.V()
}
lect.V();
mutex.y()
};
};
b) RCC
shared control (
int contador=0; }
procedure lector()
region control when (contador<20)
contador:=contador+1;
}
... realiza la lectura …
region control {
contador:=contador-1;
}
}
procedure escritor( )
{
region control when (contador==0)
... realiza la escritura ...
}
};
c) Monitores
Monitor lectores_escritores {
prívate:
int cuentalect;
bool llave_escritura;
condition escr, lect;
public:
void lectores_escritores() {
llave_escritura = false;
cuentalect = 0;
};
void finalizo_escritura( )
if (((cuentalect>0) I I (llave_escritura == true)) { escr .wait () ;
llave_escritura = true; 1
};
void Finalizo_Escritura ()
{
llave_escritura = false;
if (cuentalect == O) {
escr .Signal();
}
};
Void solicito_lectura ()
{
cuentalect++;
if ( cuentalect== 20 ) {
lect.Wait();
};
void Finalizo_Lectura()
{
cuentalect--,
if ( cuentalect >= 20 ) {
lect.Signal();
}
else
if cuentalect == O ) {
llave_escritura = false;
escr.Signal () ;
}
}
};
3.51 Solución:
const int NFILOSOFOS = 5;
bool palillos[NFILOSOFOS]=false, false, false, false, false;
Codigo Filosofo Par {
…
While (true){
// Pensando…
While (test_and_set (palillo [i]== true;
While (test_and_set (palillo [(i+1)%NFILOSOFOS]== true);
// A comer ...
palillo[i]=false;
palillol(i+1)%NFILOSOFOS]=false;
}
}
Código filosofo impar {
…
While (true){
//pensando…
While (test_and_set (palillo [(i+1)%NFILOSOFOS]== true);
While (test_and_set (palillo [(i)== true);
// A comer ...
palillo[(i+1)%NFILOSOFOS]===false;
palillol[i]%NFILOSOFOS]=false;
}
}
3.52 Asumiremos que existe una clase TipoColaPeticiones que permite manejar una
cola de peticiones: Insertar (para insertar una petició n en la cola), Extraer (para
extraer una petició n de la cola), Numero_Peticiones (nos indica el nú mero de
peticiones en la cola).
a) Semá foros
Variables globales
Semaphore mutex(1), servidor(0) ;
TipoColaPeticiones cola_peticiones;
Codigo del proceso servidor {
TipoPeticion peticion;
for ( ; ; ) {
. . .
servidor .P( ).;
mutex.P ( ) ;
peticion=cola_peticiones . Extraer ()
mutex . V ( ) ;
//Atender servicio solicitado
peticion. semcliente. V ()
…
}
}
Codigo de los procesos clientes {
/* Asumimos que uno de los campos de TipoPeticion (semcliente) es un
semaforo inicializado a 0 */
TipoPeticion mipeticion;
...
if(cola_peticiones.Numero_Peticiones()<10)
{ { cola_peticiones.Insertar(mipeticion);
servidor.V();
mutex.V(); mipeticion.semcliente.P(); else mutex.V();
b) RCC
Variables globales
ariables globales
Shared servicios {
TipoColaPeticiones cola_peticiones;
};
Shared servicio_atendido {
/* Asumimos que existe una clase TipoColaPeticionesAtendidas que permite
manejar una cola cuyos nodos contienen los identificadores de los
procesos cuyos servicios han sido atendidos por el servidor: Insertar,
Extraer, Buscar (nos indica si existe un nodo con el identificador pasado
por parametro */
TipoColaPeticionesAtendidas cola_peticiones_atendidas;
}
Codigo del proceso servidor {
TipoPetícion peticion;
for (;;)
…
region servicio
when(cola_peticiones.Numero_Peticiones()>0{ peticion=cola_peticiones.Ext
raer();
};
// Atender servicio solicitado
Región servicio_atendido{
cola_peticiones_atendidas.Insertar(peticion.Idproceso)
} ;
}
…
}
Codigo de los procesos clientes {
TipoPeticion mipeticion;
bool maxixtosuperado=false;
…
region servicio {
if (cola_peticiones.Numero_Peticiones()<10)
cola_peticiones.Insertar(mipeticion);
else maximosuperado=true;
if (!maximosuperado)
region servicio_atendido
when(cola_peticiones_atendidas.Buscar(Idproceso)
{ cola_peticiones_atendidas.Extraer(Idproceso);
} ;
…
}
c) Monitores
Variables globales
Monitor Servidor_Clientes {
private:
Condition servidor, clientes;
TipoColaPeticiones *cola_peticiones;
public:
void solicitar(TipoPeticion peticion) {
if ( cola_peticiones->Numero_Peticiones ) ==10 )
return;
cola_peticiones->Insertar(peticion);
servidor.signal(); clientes.wait(); )
TipoPeticion atender() {
if (cola_peticiones->Numero_Peticiones()==0)
servidor.wait()
return (cola_peticiones->Extraer());
}
void atendido() {
/* Si asumimos que la gestion de procesos bloqueados de las variables
condicion se realiza siguiendo una politica FIFO basta con esta variable
condicion. En caso contrario deberiamos emplear una variable condicion
para cada cliente. */
clientes.signal()
}
void Servidor_Clientes() {
cola_peticiones= new TipoColaPeticiones;
}
};
Monitor Servidor_Clientes servicio;
Codigo del proceso servidor {
TipoPeticion peticion;
for (;;) {
peticion=servicio.atender();
// Atender servicio solicitado servicio.atendido();
…
}
}
Codigo de los procesos clientes {
TipoPeticion mipeticion;
…
servicio.solicitar(mipeticion);
…
}
3.53 Solución:
a) Cuando un proceso realiza un signal, entonces sale inmediatamente del monitor; si
hay procesos detenidos por haber realizado anteriormente un wait, se producirá la
reanudació n de uno de ellos.
a) Semáforos
const int W = ...;
Semaphore mutex(1);
Semaphore cola(0) ;
int peso = O;
int esperando = O;
/* ALGORITMO A Sin preferencia para los procesos bloqueados respecto a
los recién llegados. No garantiza que un proceso pueda acceder al recurso
en un tiempo finito. También se hacen más operaciones cola.V() de las
estrictamente necesarias. */
if ( peso+wi >= W )
esperando++;
do{
mutex.V();
cola.P();
mutex.P();
while ( peso+wi >= W );
esperando--;
}
peso = peso+wi;
mutex.V();
}
/* ALGORITMO B
Con preferencia para los procesos ya bloqueados respecto a los recién
llegados.
Se lanza una cantidad de operaciones cola.V() razonablemente pequeña. ./
// las mismas variables, mas esta:
int despertar= 0;
void EmpiezaAcceso ( int wi ){
mutex.P();
if ( peso+wi >= W ){
esperando++;
do{
desbloquea_siguiente();
cola.P();
} while ( peso+wi >= W );
esperando--;
}
peso = peso+wi;
desbloquea_siguiente();
}
void desbloquea_siguiente() {
if ( despertar > 1 ) {
despertar--;
cola.V();
else {
despertar = O
mutex.V();
}
void TerminaAcceso ( int wi
mutex.P();
peso = peso - wi;
if ( esperando >0 ){
despertar= esperando;
cola.V ()
} else {
mutex.V{}
}
}
b) RCC
const int W = ...;
shared Archivo { int peso=0; }
void EmpiezaAcceso ( int wi ) {
region Archivo when peso+wi < W {
peso = peso + wi
}
}
void TerminaAcceso ( int wi ){
region Archivo
peso=peso +wi;
}
}
c) Monitores
monitor Archivo {
const int W = ...;
private int peso;
private Condition cola;
public Archivo () { peso = 0; }