UNIVERSIDAD NACIONAL JORGE BASADRE GROHMANN FACULTAD DE INGENIERÍA ESCUELA ACADÉMICO PROFESIONAL DE INGENIERÍA EN INFORMÁTICA Y SISTEMAS
PROBLEMA DE LOS CANÍBALES “SEMÁFOROS Y MONITORES”
PARALELA A CURSO: ALGORITMOS Y PROGRAMACIÓN PARALEL DOCENTE: Ing.
MARIO GAUNA CHINO
ESTUDIANTE: DIEGO ALEXANDER ESTRADA CRUZ || 2014-11904 AÑO: SEGUNDO | TURNO: TARDE | GRUPO: ! FECHA DE ELABORACIÓN: 2"#11#201$ FECHA DE ENTREGA:
01#12#201$
TACNA TACNA – PER
!"#$
El Problema de los Caníbales “Los Caníbales Comensales” 1. INTRODUCCIÓN En una tribu de caníbales todos comen de la misma olla, la cual puede albergar N raciones de comida. Cuando un caníbal quiere comer, simplemente se sirve de la olla común, a no ser que esté vacía. En ese caso, el caníbal despierta al cocinero de la tribu y espera hasta que éste haya rellenado la olla. En este problema, los eventos de sincronización son dos
!i un caníbal que quiere comer se encuentra con la olla vacía, entonces se lo
noti"ica al cocinero para que éste cocine. Cuando el cocinero termina de cocinar, entonces se lo noti"ica al caníbal que lo despertó previamente.
#n posible planteamiento para solucionar este problema podría girar en torno al uso de un sem$"oro que controlara el número de raciones disponibles en un determinado momento %de manera similar al problema del bu""er limitado&. !in embargo, este planteamiento no "acilita la noti"icación al cocinero cuando la olla esté vacía, ya que no es deseable acceder al valor interno de un sem$"oro y, en "unción del mismo, actuar de una "orma u otra. #na alternativa v$lida consiste en utilizar el patrón marcador para controlar el número de raciones de la olla mediante una variable compartida. !i ésta alcanza el valor de ', entonces el caníbal podría despertar al cocinero. (a sincronización entre el caníbal y el cocinero se realiza mediante rendezvous ).
El caníbal intenta obtener una ración.
*.
!i no hay raciones en la olla, el caníbal despierta al cocinero.
+.
El cocinero cocina y rellena la olla.
.
El cocinero noti"ica al caníbal.
-.
El caníbal come.
!"#a$
%. &PLIC&NDO U'O DE 'E()*ORO %.1.
Elemen#os Num+Ra!"ones, variable compartida que contiene el número de raciones disponibles en la olla en un determinado instante de tiempo. (u#e,, sem$"oro binario que controla el acceso a Num/aciones. Em-#, que controla cuando la olla se ha quedado vacía. *ull, que controla cuando la olla est$ llena.
%.%.
'eudo!/d"0o En el siguiente listado se muestra el pseudocódigo del proceso cocinero, el cual es muy simple ya que se basa en esperar la llamada del caníbal, cocinar y noti"icar de nuevo al caníbal.
a$ Pro!eso Co!"nero
El pseudocódigo del proceso caníbal es algo m$s comple0o, debido a que ha de consultar el número de raciones disponibles en la olla antes de comer.
b$ Pro!eso Caníbal
Como se puede apreciar, el proceso caníbal comprueba el número de raciones disponibles en la olla %línea 12&. !i no hay, entonces despierta al cocinero %línea 1-2& y espera a que éste rellena la olla %línea 132&. Estos dos eventos de sincronización guían la evolución de los procesos involucrados. Note cómo el proceso caníbal modi"ica el número de raciones asignando un valor constante. El lector podría haber optado porque "uera el cocinero el que modi"icara la variable, pero desde un punto de vista pr$ctico es m$s e"iciente que lo haga el caníbal, ya que tiene adquirido el acceso a la variable mediante el sem$"oro mutex %línea 1*2 y 1)*2&. 4osteriormente, el caníbal decrementa el número de raciones %línea 1)*2& e invierte un tiempo en comer %línea 1)2&.
. &PLIC&NDO U'O DE (ONITORE' .1.
E2em-lo
#na tribu de N caníbales come de una gran marmita común con capacidad para 3 comensales simult$neos. Cuando un comensal quiere comer, come de la marmita, a menos que no haya su"iciente comida para él. !i no hay su"iciente comida en la marmita, el caníbal despierta al cocinero y espera a que el cocinero haya rellenado la marmita con la carne de los misioneros capturados %no debe haber noti"icaciones repetidas&. 4ara rellenar la marmita el cocinero debe esperar a que todos los comensales que se encuentran actualmente comiendo terminen. El comensal que avisó debe ser el primero en comer. El cocinero, por su parte, vuelve a dormir cuando ha rellenado la marmita. Cada cierto tiempo llega el 0e"e de la tribu el cual debe esperar que todos los comensales terminen para comer solo, teniendo éste prioridad sobre los nuevos comensales.
.%.
Cons"dera!"ones
No podr$n entrar nuevos comensales a la marmita en las siguiente situaciones 5 El 0e"e est$ comiendo o esperando para comer. 5 El cocinero est$ rellenando o esperando para rellenar. El 0e"e se comporta como un comensal m$s para el cocinero y también "ue el
primero en avisarle. !e supone que la marmita llena dispone de comida para m$s de seis caníbales.
.. o
*un!"ones
3a+su4"!"en#e+!om"da $5 boolean Esta "unción es e0ecutada por los comensales %caníbales y el 0e"e& retorna si hay su"iciente comida en la marmita. No puede ser e0ecutada por dos o m$s comensales a la vez.
o Rellenar $5 Esta "unción es e0ecutada por el cocinero. o Comer $5 Es e0ecutado por los comensales. o O!"o $5 E0ecutada por los caníbales y el 0e"e cuando no est$n comiendo.
'e -"de5 6mplementar los procedimientos caníbal, 0e"e y cocinero utilizando monitores. Especi"ique la sem$ntica de los mismos en caso de ser necesario.
.6.
'olu!"/n
program Marmita; begin var cant_canibales: integer; var jefe, rellenar: boolean; var cnd_jefe, cnd_relleno, cnd_cocinero, cnd_canibal: condition; procedure comer (soy_jefe: boolean); begin if soy_jefe then begin jefe = true ; if cant_canibales > 0 or rellenar do
cnd_jefe.wait(); end ; else if cant_canibales = 6 or rellenar or jefe do
cnd_canibal.wait(); if not hay_sficiente_comida() then begin
rellenar = true; if cant_canibales = 0 then cnd_cocinero.si!nal(); cnd_relleno.wait(); end ; if not jefe and not rellenar and cant_canibales " 6 then
cnd_canibal.si!nal(); cant_canibales##; end ; procedure termine_comer (soy_jefe: boolean); begin if soy_jefe then jefe = false;
cant_canibales$$; des%ertar(); end ; procedure cocinero_inicio(); begin
cnd_cocinero.wait(); end procedure cocinero_fin(); var i: integer; begin rellenar = false;
cnd_relleno.si!nal(); && %rioridad m'ima al e a*is+ des%ertar(); end ; procedure des%ertar(); begin if cant_canibales = 0 then begin
if rellenar then
cnd_cocinero.si!nal(); else if jefe then cnd_jefe.si!nal(); end ; if not jefe and not rellenar then
cond_canibal.si!nal(); end ; begin
cant_canibales = 0; jefe = false; rellenar = false; end ; end ; procedure canibal (); begin while true do begin
marmita.comer( false); comer(); marmita.termine_comer( false); ocio(); end ; end ; procedure jefe () begin while true do begin
marmita.comer( true ); comer(); marmita.termine_comer( true); ocio(); end ; end ; procedure cocinero () begin while true do begin
marmita.cocinero_inicio(); rellenar(); marmita.cocinero_fin(); end ; end .