0% encontró este documento útil (0 votos)
444 vistas10 páginas

Barbero Dormilon C#

1. El problema plantea la situación de 5 filósofos sentados alrededor de una mesa, cada uno con un plato de fideos y un tenedor a su izquierda. 2. Para comer, cada filósofo necesita los dos tenedores adyacentes a su plato, pero sólo puede haber un filósofo comiendo a la vez para evitar bloqueos. 3. Se debe implementar un algoritmo que coordine el acceso a los tenedores sharedos para que los filósofos puedan comer sin problemas de concurrencia.

Cargado por

JalsxA
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como DOCX, PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
444 vistas10 páginas

Barbero Dormilon C#

1. El problema plantea la situación de 5 filósofos sentados alrededor de una mesa, cada uno con un plato de fideos y un tenedor a su izquierda. 2. Para comer, cada filósofo necesita los dos tenedores adyacentes a su plato, pero sólo puede haber un filósofo comiendo a la vez para evitar bloqueos. 3. Se debe implementar un algoritmo que coordine el acceso a los tenedores sharedos para que los filósofos puedan comer sin problemas de concurrencia.

Cargado por

JalsxA
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como DOCX, PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 10

BARBERO DORMILON

El barbero dormiln:

Problema planteado por Dijkstra en 1971


Una peluquera en la que hay un barbero, una silla de
peluquero y N sillas para que se sienten los clientes en espera,
si es que los hay.
Si no hay clientes presentes, el barbero se sienta en su silla
de peluquero y se duerme.
Cuando llega un cliente, ste debe despertar al barbero
dormiln.
Si llegan ms clientes mientras el barbero corta el cabello de
un cliente, se sientan (si hay sillas desocupadas) o salen de la
peluquera (si todas las sillas estn ocupadas).
Programar al barbero y los clientes.

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>

typedef enum {LLENO, CORTADO} respuesta;


#define NUM_CLIENTES 6 // Numero de clientes
#define N 3 // Numero max de clientes en la barberia

int clientes = 0; // Numero de clientes en la barberia


int quien = -1; // Cliente que esta siendo atendido

pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; //para excl mutua ops


monitor
pthread_cond_t silla, sillon, sube_sillon, dormir;

void pcliente(int i, char *s) {printf(Cliente: %d -> %s\n, i,s);}


void pbarbero (char *s) {printf(Barbero: -> %s\n, s);}

// 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);
}

void da_una_vuelta(int i, int t) {


pcliente(i,VOY a dar una vuelta); printf( durante (%d useg.)\n,t);
usleep(t);
pcliente(i,VENGO de dar una vuelta);
}
// - fin monitor

void *cliente(void *arg) {


long int i=(long int) arg;
do {da_una_vuelta(i,rand()%10000);} while (entra_barberia(i)==LLENO);
}

void *barbero(void *arg) {


while (1) {espera_cliente(); corta_pelo(); fin_corte();}
}

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);
}

LECTORES ESCRITORES CON PRIORIDAD


ESCRITORES
Lectores y escritores:

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

Creacin de un proceso padre y de su proceso hijo (lectores, escritores).


Descripcin
escribir( ); Esta funcin implementa el acceso a un recurso compartido, que ser la
variable que contabiliza el total de veces que el usuario escribe. En esta funcin se han
incluido varias llamadas al macro TP. Este macro implementa un retardo aleatorio con el fin
de dar cierto tiempo a que ocurran interrupciones que puedan detener la ejecucin del
proceso en su cuanto de tiempo asignado por el S.O.. En nuestro caso, es necesario
realizar unas cuantas llamadas para dar tiempo a que todos los usuarios tengan oportunidad
de escribir.
lectura( ); Permite que el lector pueda acceder al recurso. Una vez que acaba de leer se
encarga de dejar el recurso para que sean de nuevo utilizado (por l o por otros). Para ello
se basa en funciones de manejo de semforos y memoria compartida.
Utiliza las siguientes funciones:

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.

1 Programa la solucin al problema de lectores / escritores con prioridad de escritores.


NOTA: esta vez necesitamos contabilizar localmente tanto el nmero de lectores como el
nmero de escritores en el sistema. Recuerda que aunque no tengan la prioridad, si un
lector estaba ya en el sistema los escritores han de bloquearse.

Solucin en Pseudocdigo:

#define TRUE 1

semforo mutex_r; // Controla exclusin mutua para el n de lectores


semforo mutex_w; // Controla exclusin mutua para el n de escritores
semforo lectores; //Controla entrada de lectores
semforo escritores; //Controla entrada de escritores

int nw = 0; //Contabiliza n de escritores


int nr = 0; //Contabiliza n de lectores

main(){

IniciarSemaforo (mutex_r, 1);


IniciarSemaforo (mutex_w, 1);
IniciarSemaforo (lectores, 1);
IniciarSemaforo (escritores, 1);

}
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);

LeerDatos (); //Seccion Critica

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

Por turno cclico

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).

Resolucin de conflictos en colas de tenedores

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.

El portero del comedor

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

/* Solucion a la cena de los filosofos


mediante semaforos. */
#define TRUE1
#define N5
#define LEFT(x)(((x)-1)%N)
#define RIGHT(X)(((X)+1)%N)
typedef struct
{
int value;
/* Lista de procesos. */
}
semaphore;
typedef enum
{
THINKING, HUNGRY, EATING
}
status;
/* Estado de cada filosofo. */
status estado[N];
/* Semaforo para exclusion mutua. */
semaphore mutex,
/* Semaforo para bloquear los filosofos adyacentes. */
s[N];
main ()
{
extern status estado[N];
extern semaphore mutex, s[N];
int i, sw = 1;
void Philosopher (int);
/* Inicializamos los semaforos. */
InitSemaphore (mutex, 1);
for (i = 0; i < N; i++)
InitSemaphore (s[i], 0);
/* Inicializamos los estados. */
for (i = 0; i < N; i++)
estado[i] = THINKING;
/* Inicializamos los filosofos. */
for (i = 0; (i < N) && (sw); i++)
if (!(sw = fork ()))
Philosopher (i);
}
void
Philosopher (int i)
{
void think (), eat (), TakeForks (int), PutForks (int);
while (TRUE)
{
think ();
/* Obtiene dos tenedores o se bloquea. */
TakeForks (i);
eat ();
PutForks (i);
}
}
void
TakeForks (int i)
{
void test (int);
extern semaphore mutex, s[N];
extern status estado[N];
/* Acceso a seccion critica. */
wait (mutex);
estado[i] = HUNGRY;
/* Intenta tomar los dos tenedores. */
test (i);
signal (mutex);
/* Se bloquea si no consiguio los tenedores. */
wait (s[i]);
}
void
PutForks (int i)
{
void test (int);
extern semaphore mutex;
extern status estado[N];
/* Acceso a seccion critica. */
wait (mutex);
estado[i] = THINKING;
/* Comprueba si el vecino izquierdo puede comer ahora. */
test (LEFT (i));
/* Comprueba si el vecino derecho puede comer ahora. */
test (RIGHT (i));
signal (mutex);
}
void
test (int i)
{
extern semaphore s[N];
extern status estado[N];
if (estado[i] == HUNGRY && estado[LEFT (i)] != EATING &&
estado[RIGHT (i)] != EATING)
{
estado[i] = EATING;
signal (s[i]);
}
}

También podría gustarte