Barbero Dormilon C#
Barbero Dormilon C#
El barbero dormiln:
Por lo que se ve, hay variables tipo bandera, que debe ser consultadas al iniciar un proceso,
esto es clasico en los sistemas operativos multiprogramacin.
El problema consiste en una barbera en la que trabaja un barbero que tiene un nico silln
de barbero y varias sillas para esperar. Cuando no hay clientes, el barbero se sienta en una
silla y se duerme. Cuando llega un nuevo cliente, ste o bien despierta al barbero o si el
barbero est afeitando a otro cliente se sienta en una silla (o se va si todas las sillas estn
ocupadas por clientes esperando). El problema consiste en realizar la actividad del barbero
sin que ocurran condiciones de carrera. La solucin implica el uso de semforos y objetos
de exclusin mutua para proteger la seccin critica.
Un semforo es una variable protegida (o tipo abstracto de datos) que constituye el mtodo
clsico para restringir o permitir el acceso a recursos compartidos (por ejemplo, un recurso
de almacenamiento) en un entorno de multiprocesamiento.
El problema del peluquero dormiln (originalmente, el barbero dormiln) es un clsico
de la Programacin Concurrente. En l se propone la discusin sobre cmo gestionar el
transito por una pequea peluquera (recurso compartido), por parte de dos tipos de
procesos: el peluquero y los clientes. El enunciado sugiere que durante la ejecucin la
interaccin entre el peluquero y un cliente se puede producir muy a menudo y que, por
tanto, deben establecerse los mecanismos de sincronizacin adecuados para evitar que los
dos colisionen dentro la peluquera; es decir, asegurar uno slo es el que se mueve en
cada momento.
#include <stdlib.h>
#include <stdio.h>
#include <semaphore.h>
#include <pthread.h>
#include <math.h>
// inicio monitor
int entra_barberia(int i) {
pcliente(i,ENTRO en la barberia);
pthread_mutex_lock( &m );
if (clientes >= N) {pthread_mutex_unlock(&m ); return LLENO;} // No cabe
else {
clientes++;
if (clientes==1) {
pcliente(i,DESPIERTO al barbero);
pthread_cond_signal(&dormir);
}
else {
cliente(i,ESPERO mi turno);
pthread_cond_wait(&silla, &m );
pthread_cond_signal(&sube_sillon);
}
quien = i;
pthread_cond_wait (&sillon, &m ); /* Esperar a que acabe el corte.*/
pcliente(i,MI PELO TAN LINDAMENTE CORTADO!!!! ADIEU! \n);
pthread_mutex_unlock(&m );
return CORTADO;
}
}
void espera_cliente() {
pthread_mutex_lock( &m );
if (!clientes) {
pbarbero(ME VOY A DORMIR);
pthread_cond_wait(&dormir,&m);
pbarbero(YA VOYYYY!!!);
}
else {
pbarbero(QUE PASE EL SIGUIENTE!!!!);
pthread_cond_signal(&silla );
pthread_cond_wait(&sube_sillon,&m);
}
pthread_mutex_unlock( &m);
}
void fin_corte() {
pthread_mutex_lock(&m);
pthread_cond_signal(&sillon); clientes; pbarbero(FIN CORTE);
pthread_mutex_unlock(&m);
}
void corta_pelo() {
int r =rand()%10000;
//usleep(10); (con sube_sillon, ya no es necesario)
pthread_mutex_lock(&m ); // Protege el acceso a la variable quien
pbarbero(CORTANDO EL PELO (Chis, Chas, Chis, Chas));
printf( A %d (%d useg.)\n,quien,r);
pthread_mutex_unlock(&m );
usleep(r);
}
int main(void) {
long int i;
pthread_t id_clientes[NUM_CLIENTES], id_barbero;
srand( (unsigned)time( NULL ) );
pthread_cond_init(&silla, 0);
pthread_cond_init(&sillon, 0);
pthread_cond_init(&sube_sillon, 0);
pthread_cond_init(&dormir, 0);
pthread_create(&id_barbero, NULL, barbero, NULL); sleep(1);
for (i=0; i<NUM_CLIENTES; i++) pthread_create(&id_clientes[i], NULL, cliente,
(void *) i);
for (i=0; i<NUM_CLIENTES; i++) pthread_join(id_clientes[i], NULL);
}
Problema
Hay un objeto de datos(fichero de texto) que es utilizado por varios procesos, unos leen y
otro que escribe.
Solo puede utilizar el recurso un proceso y solo uno, es decir, o bien un proceso estar
escribiendo o bien leyendo, pero nunca ocurrir simultneamente (teniendo en cuenta que si
no lo esta utilizando nadie, tendr preferencia el escritor ante el lector).
Se considera a cada usuario(lector y escritor) como dos procesos y al fichero en cuestin
como un recurso. De modo que, para que un proceso acceda al recurso que necesita,
tenemos que considerar a cada usuario (lector y escritor) como dos semforos. Estos
semforos son binarios y valen 0 si el recurso (fichero) est siendo utilizado por otro
proceso y 1 si dicho recurso est disponible.
La solucin de este problema se basa en implementar un algoritmo eficiente (vase
algoritmo) en el manejo de semforos y memoria compartida que seguidamente
describimos. A lo largo del programa se utilizan funciones necesarias para el manejo de
memoria compartida (vase rshmem.h Y rshmem.c) manejo de semforos (vase
semaph.c .)
Para que el problema est bien resuelto se tiene que cumplir:
No se puede hacer esperar a ningn proceso lector si ningn proceso escritor accede al
recurso.
Cuando un escritor debe realizar su tarea, debe ocurrir cuanto antes, sin que deban
interferir los procesos lectores.(Para ello se establecen prioridades).
Funcin Main
Manejo de semaforos:
semWait ( )
semSignal ( )
semOpen ( )
semClose ( )
Manejo de memoria compartida:
Cada vez que escribe un usuario lo refleja en el incremento de la variable de memoria
compartida.
Cuando los lectores y escritores han realizado la tarea que desean(leer y escribir) un
nmero M de veces prefijado (3) se lo comunican al padre, no sin antes haber cerrado
adecuadamente todos los semforos utilizados en esta funcin.
Solucin en Pseudocdigo:
#define TRUE 1
main(){
}
void Lector ()
{
extern SEMAFORO mutex_r, lectores, escritores;
extern int nr;
while (TRUE)
{
wait(lectores);
wait (mutex_r);
nr++;
if(nr==1)
wait(escritores);
signal(mutex_r);
signal(lectores);
wait (mutex_r);
nr;
if (nr == 0)
signal (escritores);
signal (mutex_r);
}
}
void Escritor ()
{
extern SEMAFORO mutex_w, lectores, escritores;
extern int nw;
while (TRUE)
{
wait (mutex_w);
nw++;
if(nw==1)
wait(lectores);
signal(mutex_w);
wait(escritores);
EscribirDatos (); //Seccion Critica
signal (escritores);
wait(mutex_w);
nw;
if(nw==0)
signal(lectores);
signal(mutex_w)
}
}
FILOSOFOS COMENSALES
Cinco Filsofos se sientan alrededor de una mesa y pasan su vida cenando y pensando.
Cada filsofo tiene un plato de fideos y un tenedor a la izquierda de su plato. Para comer
los fideos son necesarios dos tenedores y cada filsofo slo puede tomar los que estn a su
izquierda y derecha. Si cualquier filsofo coge un tenedor y el otro est ocupado, se
quedar esperando, con el tenedor en la mano, hasta que pueda coger el otro tenedor, para
luego empezar a comer.
Si dos filsofos adyacentes intentan tomar el mismo tenedor a una vez, se produce
una condicin de carrera: ambos compiten por tomar el mismo tenedor, y uno de ellos se
queda sin comer.
Si todos los filsofos cogen el tenedor que est a su derecha al mismo tiempo, entonces
todos se quedarn esperando eternamente, porque alguien debe liberar el tenedor que les
falta. Nadie lo har porque todos se encuentran en la misma situacin (esperando que
alguno deje sus tenedores). Entonces los filsofos se morirn de hambre. Este bloqueo
mutuo se denomina interbloqueo o deadlock.
El problema consiste en encontrar un algoritmo que permita que los filsofos nunca se
mueran de hambre.
Algunas Posibles Soluciones
Se empieza por un filsofo, que si quiere puede comer y despus pasa su turno al de la
derecha. Cada filsofo slo puede comer en su turno. Problema: si el nmero de filsofos
es muy alto, uno puede morir de hambre antes de su turno.
Varios turnos
Se establecen varios turnos. Para hacerlo ms claro supongamos que cada filsofo que
puede comer (es su turno) tiene una ficha que despus pasa a la derecha. Si por ejemplo hay
7 comensales podemos poner 3 fichas en posiciones alternas (entre dos de las fichas
quedaran dos filsofos).
Se establecen turnos de tiempo fijo. Por ejemplo cada 5 minutos se pasan las fichas (y los
turnos) a la derecha.
En base al tiempo que suelen tardar los filsofos en comer y en volver a tener hambre, el
tiempo de turno establecido puede hacer que sea peor solucin que la anterior. Si el tiempo
de turno se aproxima al tiempo medio que tarda un filsofo en comer esta variante da muy
buenos resultados. Si adems el tiempo medio de comer es similar al tiempo medio en
volver a tener hambre la solucin se aproxima al ptimo.
Colas de tenedores
Cuando un filsofo quiere comer se pone en la cola de los dos tenedores que necesita.
Cuando un tenedor est libre lo toma. Cuando toma los dos tenedores, come y deja libre los
tenedores.
Visto desde el otro lado, cada tenedor slo puede tener dos filsofos en cola, siempre los
mismos.
Esto crea el problema comentado de que si todos quieren comer a la vez y todos empiezan
tomando el tenedor de su derecha se bloquea el sistema (deadlock).
Cada vez que un filsofo tiene un tenedor espera un tiempo aleatorio para conseguir el
segundo tenedor. Si en ese tiempo no queda libre el segundo tenedor, suelta el que tiene y
vuelve a ponerse en cola para sus dos tenedores.
Si un filsofo A suelta un tenedor (porque ha comido o porque ha esperado demasiado
tiempo con el tenedor en la mano) pero todava desea comer, vuelve a ponerse en cola para
ese tenedor. Si el filsofo adyacente B est ya en esa cola de tenedor (tiene hambre) lo toma
y si no vuelve a cogerlo A.
Es importante que el tiempo de espera sea aleatorio o se mantendr el bloqueo del sistema.
Se indica a los filsofos que abandonen la mesa cuando no tengan hambre y que no
regresen a ella hasta que vuelvan a estar hambrientos (cada filsofo siempre se sienta en la
misma silla). La misin del portero es controlar el nmero de filsofos en la sala, limitando
su nmero a n-1, pues si hay n-1 comensales seguro que al menos uno puede comer con los
dos tenedores.
Solucin
Por Semforos