PRINCIPIOS DEL INTERBLOQUEO
El interbloqueo se puede definir como el bloqueo permanente de un conjunto de procesos que compiten por los recursos del sistema o bien se comunican unos con otros. A diferencia de otros problemas de la gestión concurrente de procesos, no existe una solución eficiente para el caso general.
Todos los interbloqueos suponen necesidades contradictorias de recursos por parte de dos o más procesos.
EJEMPLOS DE INTERBLOQUEO
Ejemplo 1: Interbloqueo de tráfico
Cuatro coches llegan aproximadamente en el mismo instante a un cruce de cuatro caminos. Los cuatro cuadrantes de la intersección son los recursos compartidos sobre los que se demanda control; por tanto, si los coches desean atravesar el cruce, las necesidades de recursos son las siguientes:
- El coche que va hacia el norte necesita los cuadrantes 1 y 2.
- El coche que va hacia el oeste necesita los cuadrantes 2 y 3.
- El coche que va hacia el sur necesita los cuadrantes 3 y 4.
- El coche que va hacia el este necesita los cuadrantes 4 y 1.
La norma mas habitual en la carretera es que un coche en un cruce de cuatro caminos debe ceder el paso al coche que está a su derecha. Esta norma funciona si solo hay dos o tres coches en el cruce. Por ejemplo, si solo llegan al cruce los coches del norte y del oeste, el coche del norte esperará hasta que el del oeste pase. Sin embargo, si los cuatro coches llegan al mismo tiempo cada uno se abstendrá de entrar en el cruce, provocando interbloqueo. Si todos los coches ignoran las normas y entran (con cuidado) en el cruce, cada coche obtendrá un recurso (un cuadrante) pero no podrá continuar porque el segundo recurso que necesita ya ha sido invadido por otro coche. De nuevo, se tiene interbloqueo.
Ejemplo 2: Cruce en un puente (es parecido al interbloqueo de trafico)
En una carretera de dos direcciones, donde en un determinado cruce con la vía del ferrocarril, se ha construido un puente que solo deja pasar vehículos en un solo sentido. El bloqueo ocurre cuando dos carros intentan pasar por el puente al mismo tiempo.
Una manera de resolver el bloqueo es: el conductor situado en uno de los extremos es lo suficientemente educado que deja pasar en primer lugar al del otro extremo y luego pasa él.
Este ejemplo nos muestra como sucede el interbloqueo en nuestra vida diaria.
Ejemplo 3
Dos procesos desean imprimir cada uno un enorme archivo en cinta. El proceso A solicita el permiso para utilizar la impresora, el cual se le concede. Es entonces cuando el proceso B solicita permiso para utilizar la unidad de cinta y se le otorga. El proceso A solicita entonces la unidad de cinta, pero la solicitud es denegada hasta que B la libere. Por desgracia, en este momento, en vez de liberar unidad de cinta, B solicita la impresora. Los procesos se bloquean en ese momento y permanecen así por siempre.
RECURSOS
Un sistema se compone de un numero finito de recursos que se distribuyen entre varios tipos:
- Físicos: Ciclo de cpu, espacio en memoria, dispositivos de e/s (impresoras, unidades de cinta, etc.)
- Lógicos: Ficheros, tablas del sistemas, semáforos.
Por lo general, una computadora tiene distintos recursos que pueden ser otorgados. Algunos recursos podrán tener varias instancias idénticas, como es el caso de tres unidades de cinta. Si se tienen disponibles varias copias de un recurso, cualquiera de ellas se pude utilizar para satisfacer cualquier solicitud del recurso. Un recurso es cualquier cosa que solo puede ser utilizada por un único proceso en un instante dado.
Los recursos son de dos tipos:
- Apropiable
- No apropiables
Un recurso apropiable es aquel que se puede tomar del proceso que lo posee sin efectos dañinos. La memoria es un ejemplo de recurso apropiable.
Por el contrario, un recurso no apropiable, es aquel que no se puede tomar de su poseedor activo sin provocar un fallo de calculo. Si un proceso comienza a imprimir una salida, se toma la impresora y se le da a otro proceso, el resultado será una salida incomprensible. Las impresoras no son apropiables.
Los interbloqueos se relacionan con los recursos no apropiables. Lo usual es que los bloqueos asociados a recursos apropiables se pueden resolver, mediante la reasignación de recursos de un proceso a otro.
La secuencia de eventos necesaria para utilizar un recurso es:
- Solicitar el recurso
- Utilizar el recurso
- Liberar el recurso
Si el recurso no esta disponible cuando se le solicita, el proceso solicitante debe esperar. En algunos sistemas operativos, el proceso se bloquea de manera automática al fallar una solicitud de un recurso y se despierta cuando dicho recurso esta disponible. En otros sistemas la solicitud falla con un código de error y el proceso solicitante debe esperar un poco e intentar de nuevo.
Un proceso cuya solicitud de un recurso ha sido denegada entra por lo general en un ciclo, en el cual solicita el recurso, duerme e intenta de nuevo.
Aunque este proceso no esta bloqueado, para todos los efectos esta como bloqueado, puesto que no puede hacer ninguna labor útil.
El interbloque se puede definir entonces de la siguiente forma:
Un conjunto de procesos se encuentra en estado de interbloqueo cuando cada uno de ellos espera un suceso que solo puede originar otro proceso del mismo conjunto.
En la mayoría de los casos, el evento que espera cada proceso es la liberación de cierto recurso que posee por el momento otro miembro del conjunto. En otras palabras, cada miembro del conjunto de procesos bloqueados espera un recurso poseído por un proceso bloqueado. Ninguno de los procesos puede continuar su ejecución, ni liberar recursos, y puede ser despertado.
CONDICIONES PARA PRODUCIR INTERBLOQUEO
En la política del sistema operativo, deben darse tres condiciones para que pueda producirse un interbloqueo:
1- Condición de exclusión mutua: Cada recurso esta asignado a un único proceso o esta disponible.
2- Condición de posesión y espera: Los procesos que tienen, en un momento dado, recursos asignados con anterioridad, pueden solicitar nuevos recursos.
3- Condición de no apropiación: Los recursos otorgados con anterioridad no pueden ser forzados a dejar un proceso. El proceso que los posee debe liberarlos en forma explicita.
En la mayoría de los casos, estas condiciones son bastantes necesarias. La exclusión mutua hace falta para asegurar la consistencia de resultados y la integridad de la base de datos. De forma similar, la apropiación no se puede aplicar arbitrariamente y, cuando se encuentran involucrados recursos de datos, debe estar acompañada de un mecanismo de recuperación y reanulación, que devuelva un proceso y sus recursos a un estado previo adecuado, desde el que el proceso puede finalmente repetir sus acciones.
Puede no existir interbloqueo con solo estas tres condiciones. Para que se produzca interbloqueo, se necesita una cuarta condición:
4- Condición de espera circular (o circulo vicioso de espera): Debe existir una cadena circular de dos o mas procesos, cada uno de los cuales espera un recurso poseído por el siguiente miembro de la cadena.
Las tres primeras condiciones son necesarias, pero no suficientes, para que exista interbloqueo. La cuarta condición es, en realidad, una consecuencia potencial de las tres primeras. Es decir, dado que se producen las tres primeras condiciones, puede ocurrir una secuencia de eventos que desemboque en un circulo vicioso de espera irresoluble. El circulo de espera de la condición 4 es irresoluble porque se mantienen las tres primeras condiciones. Las cuatro condiciones en conjunto constituyen una condición necesaria y suficiente para el interbloqueo.
PREVENCIÓN DEL INTERBLOQUEO
La estrategia básica de la prevención del interbloqueo consiste, a grandes rasgos, en diseñar su sistema de manera que esté excluida, a priori, la posibilidad de interbloqueo.
Los métodos para prevenir el interbloqueo son de dos tipos:
- Los métodos indirectos que consisten en impedir la aparición de alguna de las tres condiciones necesarias para que se de el interbloqeo.
- Los métodos directos que consisten en evitar la aparición del circulo vicioso de espera.
Exclusión mutua Si ningún recurso se puede asignar de forma exclusiva, no se producirá interbloqueo. Sin embargo, existen recursos para los que no es posible negar la condicion de exclusión mutua. No obstante, es posible eliminar esta condicion en algunos procesos. Por ejemplo, una impresora es un recurso no compatible pues si se permite que dos procesos escriban en la impresora al mismo tiempo, la salida resulta caótica. Pero con el spooling de salida varios procesos pueden generar salida al mismo tiempo. Puesto que el spooler nunca solicita otros recuersos, se elimina el bloqueo originado por la impresora.
El inconveniente es que no todos los recursos pueden usarse de esta forma (por ejemplo, la tabla de procesos no se presenta al spooling y, ademas, la implementacion de esta técnica puede introducir nuevos motivos de interbloqueo, ya que el spooling emplea una zona de disco finita)
Retencion y espera La condicion de retencion y espera puede prevenirse exigiendo que todos los procesos soliciten todos los recursos que necesiten a un mismo tiempo y bloqueando el proceso hasta que todos los recursos puedan concederse simultáneamente. Esta solucion resulta ineficiente por dos factores:
- En primer lugar, un proceso puede estar suspendido durante mucho tiempo, esperando que concedan todas sus solicitudes de recursos, cuando de hecho podria haber avanzado con solo algunos de los recursos.
- Y en segundo lugar, los recursos asignados a un proceso pueden permanecer sin usarse durante periodos considerables, tiempo durante el cual se priva del acceso a otros procesos.
No apropiación La condición de no apropiación puede prevenirse de varias formas. Primero, si a un proceso que retiene ciertos recursos se le deniega una nueva solicitud, dicho proceso deberá liberar sus recursos anteriores y solicitarlos d eneuvo, cuando sea necesario, junto con el recurso adicional. Por otra parte, si un proceso solicita un recurso que actualmente esta retenido por otro proceso, el sistema operativo debe expulsar al segundo proceso y exigirle que libere sus recursos. Este ultimo esquema evitará el interbloqueo sólo si nho hay dos procesos que posean la misma prioridad.
Esta técnica es práctica sólo cuando se aplica a recursos cuyo estado puede salvarse y restaurarse más tarde de una forma facil, como es el caso de un procesador.
Circulo vicioso de espera La condición del circulo vicioso de espera puede prevenirse definiendo una ordenación lineal de los tipos de recursos. Si a un proceso se le han asignado recursos de tipo R, entonces sólo podrá realizar peticiones posteriores sobre los recursos de los tipos siguientes a R en la ordenación.
Para comprobar el funcionamiento de esta estrategia, se asocia un índice a cada tipo de recurso. En tal caso, el recurso Ri antecede a Rj en la ordenación si i<j. Entonces, supóngase que dos procesos A y B, están interbloqueados, porque A ha adquirido Ri y solicitado Rj, mientras que B ha adquirido Rj y solicitado Ri. Esta condición es imposible porque implica que i<j y j<i.
Como en la retención y espera, la prevención del circulo vicioso de espera puede ser ineficiente, retardando procesos y denegando accesos a recursos innecesariamente.
PREDICCIÓN DEL INTERBLOQUEO
Una forma de resolver el problema del interbloqueo, que se diferencia sutilmente de la prevención, es la predicción del interbloqueo. En la prevención de interbloqueo, se obligaba a las solicitudes de recursos a impedir que sucediera , por lo menos, alguna de las cuatro condiciones de interbloqueo. Esto se hace indirectamente, impidiendo la aparición de una de las tres condiciones necesarias (exclusión mutua, retención y espera, no apropiación) o directamente, impidiendo la aparición de un circulo viciosos de espera. Se llega así a un uso ineficiente de los recursos y una ejecución ineficiente de los procesos. Con predicción del interbloqueo, por otro lado, se pueden alcanzar las tres condiciones necesarias, pero se realizan elecciones acertadas para asegurar que nunca se llega al punto de interbloqueo. La predicción, por lo tanto, permite más concurrencia que la prevención.
Con predicción del interbloqueo, se decide dinámicamente si la petición actual de asignación de un recurso podría, de concederse, llevar potencialmente a un interbloqueo. La predicción del interbloqueo necesita, por lo tanto, conocer las peticiones futuras de recursos.
Enfoques para la predicción del interbloqueo:
- No iniciar un proceso si sus demandas pueden llevar a interbloqueo.
- No conceder una solicitud de incrementar los recursos de un proceso si esta asignación puede llevar a interbloqueo.
Negativa de iniciación de procesos Confedérese un sistemas de n procesos y m tipos diferentes de recursos. Se definen los vectores y matrices siguientes:
Recursos = (R1, R2, … Rm) cantidad total de cada recurso en el sistema
Disponible = (D1, D2, … Dm) cantidad total de cada recurso sin asignar a los procesos
C11 C12 … C1m
C21 C22 … C2m
. . . . . . . . . . . .
Cn1 Cn2 … Cnm
Demanda = exigencias de recursos para cada proceso
A11 A12 … A1m
A21 A22 … A2m
. . . . . . . . . . . .
An1 An2 … Anm
Asignación = asignación actual
La matriz Demanda indica las exigencias máximas de recursos para cada proceso, con una fila para cada uno. Es decir, Cij = demanda del recurso j por parte del proceso i. Esta información debe declararse por adelantado para que funcione la predicción de interbloqueo. De forma similar, Aij = asignación del recurso j al proceso i. Se puede ver que se cumplen las siguientes relaciones:
Para todo i, Ri = Di + Σ Aki : todos los recursos están asignados o disponibles. Para todo k e i, Cki <= Ri: ningún proceso puede demandar más recursos que la cantidad total de recursos del sistema Para todo k e i, Aki <= Cki: ningún proceso tiene asignados más recursos de cualquier tipo que los que ha declarado necesitar.
Con estas tres cantidades, se puede definir una política de predicción del interbloqueo que rechace iniciar un nuevo proceso si sus exigencias de recursos pueden conducir a un intebloqueo. Un nuevo proceso Pn+1 comenzará sólo si:
Ri >= C(n+1)i + Σ Cki, para todo i
Es decir, un proceso comenzará sólo si puede servirse la demanda máxima de todos los procesos actuales más la del nuevo proceso. Esta estrategia es poco óptima, puesto que asume el caso peor: que todos los procesos expresen su demanda máxima a la vez.
Negativa de asignación de recursos La estrategia de negar la asignación de recursos, denominada algoritmo del banquero, fue propuesta por primera vez por Dijkstra, que usó este nombre por la analogía de este problema con el de un banco cuando los clientes quieren obtener dinero prestado. Los clientes sería los procesos y el dinero a prestar, los recursos. Si se enuncia de esta manera, el banco tiene una reserva limitada de dinero para prestar y un conjunto de clientes con líneas de crédito. Un cliente puede elegir pedir dinero a cargo de la línea de crédito en un instante dado y no hay garantía de que el cliente realice ninguna reposición hasta después de sacar la cantidad máxima. El banquero puede rechazar un préstamo a un cliente si hay riesgo de que el banco no tenga fondos suficientes para hacer préstamos futuros que los clientes finalmente repondrán.
Para empezar se definen los conceptos de estado y de estado seguro. Considérese un sistema con un número fijo de procesos. Así pues, el estado estará formado por los dos vectores, Recursos y Disponible, y las dos matrices, Demanda y Asignación, definidas anteriormente. Un estado seguro es un estado en el cual existe al menos una secuencia que no lleva al interbloqueo ( es decir, todos los procesos pueden ejecutarse hasta el final). Un estado inseguro es, naturalmente, un estado que no es seguro.
El algoritmo del banquero usa una tabla de recursos para saber cuántos recursos tiene de todo tipo. También requiere que los procesos informen del máximo de recursos que va a usar de cada tipo. Cuando un proceso pide un recurso, el algoritmo verifica si asignándole ese recurso todavía le quedan otros del mismo tipo para que alguno de los procesos en el sistema todavía se le pueda dar hasta su máximo. Si la respuesta es afirmativa, el sistema se dice que está en ‘estado seguro’ y se otorga el recurso. Si la respuesta es negativa, se dice que el sistema está en estado inseguro y se hace esperar a ese proceso.
Los algoritmos siguientes muestran una versión abstracta de la logica de predicción del interbloqueo. Con el estado del sistema definido por la estructura de datos estado, solicitud [*] es un vector que define los recursos pedidos por el proceso i. En primer lugar, se hace una comprobación para asegurar que la solicitud no excede la demanda inicial del proceso. Si la solicitud es válida, el paso siguiente es determinar si es posible satisfacer la solicitud, esto es, si hay suficientes recursos disponibles. Si no es posible, el proceso se suspende. Si es posible, el paso final es determinar si es seguro satisfacer la solicitud. Para hacer esto, se prueba a asignar los recursos al proceso i desde nuevo_estado. Después, se realiza un test d seguridad usando el algoritmo del banquero.
Estructura de datos globales
struct estado
{
int recursos [m];
int disponible [m];
int demada [n] [m];
int asignación [n] [m];
}
Algoritmo de asignación de recursos
if (asignación[i, ] + solicitud [*] > demanda [I, *])
{
< error >; /*-- solicitud total > demanda */
}
else if (solicitud [*] > disponible [*])
{
< suspender proceso > ;
}
else /*-- simular asignación */
{
< definir nuevo_estado como:
asignación[i, ] = asignación[i, ] + solicitud [*]:
disponible [*] = disponible [*] – solicitud [*] >;
}
if (seguro (nuevo_estado))
{
< realizar asignación >;
}
else
{
< restaurar estado original >;
< suspender proceso >;
}
Algoritmo de comprobación de estado seguro (algoritmo del banquero)
booleano seguro (estado S)
{
int disponible_actual [m];
proceso resto [< número de procesos >];
disponible_actual = disponible;
resto = {todos los procesos};
posible = true;
while (posible)
{
encontrar un PK en resto tal que
demanda [k, *] – asignación [k, *] < = disponible_actual;
if (encontrado) /*-- simular ejecución de P */
{
disponible_actual = dispible_actual + asignación [k, *];
resto = resto – {PK};
}
else
posible = falso;
}
seguro (resto = = null);
}
La predicción del interbloqueo tiene la ventaja de que no es necesario expulsar y hacer retroceder procesos, como en la detección del interbloqueo, y es menos restrictiva que la prevención. Sin embargo, su uso supone una serie de restricciones como las siguientes:
- Se debe presentar la máxima demanda de recursos por anticipado.
- Los procesos a considerar deben ser independientes, es decir, que el orden en que se ejecuten no debe estar forzado por condiciones de sincronización.
- Debe haber un número fijo de recursos a repartir y un número fijo de procesos.
- Los procesos no pueden finalizar mientras retengan recursos.
DETECCIÓN DEL INTERBLOQUEO
Las estrategias de prevención de interbloqueo son muy conservadoras; resuelven el problema limitando el acceso a recursos e imponiendo restricciones sobre los procesos. En cambio, las estrategias de detección de interbloqueo, no limitan el acceso a recursos ni restringen las acciones del proceso. Con la detección del interbloqueo, se concederán los recursos que los procesos necesiten siempre que sea posible. Periódicamente, el S. O. ejecuta un algoritmo que permite detectar la condición de circulo vicioso de espera.
La detección del interbloqueo es el proceso de determinar si realmente existe un interbloqueo e identificar los procesos y recursos implicados en él. Una posibilidad detectar un interbloqueo es monitorear cada cierto tiempo el estado de los recursos. Cada vez que se solicita o se devuelve un recurso, se actualiza el estado de los recursos y se hace una verificación para observar si existe algún ciclo.
Este método está basado en suponer que un interbloqueo no se presente y que los recursos del sistema que han sido asignados, se liberarán en el momento que otro proceso lo requiera.
Algoritmo de detección del interbloqueo Una comprobación para interbloqueo puede hacerse con igual o menor frecuencia que cada solicitud de recursos, dependiendo de que tan probable es que ocurra un interbloqueo. Comprobar cada solicitud de recursos tiene dos ventajas: Conduce a la detección temprana y el algoritmo es simple, de manera relativa porque se basa en cambios crecientes al estado del sistema. Además, las comprobaciones frecuentes consumen un tiempo considerable de procesador.
Los algoritmos de detección de bloqueos implican cierta sobrecarga en tiempo de ejecución:
surge el siguiente interrogante:
¿ compensa la sobrecarga implicita en los algoritmos de detección de bloqueos, el ahorro potencial de localizarlos y romperlos ?.
El empleo de algoritmos de detección de interbloqueo implica cierto gasto extra durante la ejecución. Así pues, se presenta de nuevo la cuestión de costeabilidad, tan habitual en los sistemas operativos. Los algoritmos de detección de interbloqueo determinan por lo general si existe una espera circular.
Recuperación de Interbloqueo
Cuando se ha detectado que existe un interbloqueo, podemos actuar de varias formas. Una posibilidad es informar al operador que ha ocurrido un interbloqueo y dejar que el operador se ocupe de él manualmente. La otra posibilidad es dejar que el sistema se recupere automáticamente del interbloqueo. Dentro de esta recuperación automática tenemos dos opciones para romper el interbloqueo: Una consiste en abortar uno o más procesos hasta romper la espera circular, y la segunda es apropiar algunos recursos de uno o más de los procesos bloqueados.
La recuperación después de un interbloqueo se complica porque puede no estar claro que el sistema se haya bloqueado. Las mayorías de los Sistemas Operativos no tienen los medios suficientes para suspender un proceso, eliminarlo del sistema y reanudarlo más tarde.
Actualmente, la recuperación se suele realizar eliminando un proceso y quitándole sus recursos. El proceso eliminado se pierde, pero gracias a esto ahora es posible terminar. Algunas veces es necesario, eliminar varios procesos hasta que se hayan liberado los recursos necesarios para que terminen los procesos restantes.
Los procesos pueden eliminarse de acuerdo con algún orden de prioridad, aunque es posible que no existan prioridades entre los procesos bloqueados, de modo que el operador necesita tomar una decisión arbitraria para decidir que procesos se eliminarán.
Recuperación Manual
Está forma de recuperación consiste en avisarle al administrador o al operador del sistema que se ha presentado un interbloqueo, y será el administrador el que solucione dicho problema de la manera más conveniente posible, de modo que su decisión no afecte demasiado a al usuario del proceso en conflicto, y sobre todo que no afecte a los demás usuarios del sistema.
Abortar los Procesos
Para eliminar interbloqueos abortando un proceso, tenemos dos métodos; en ambos, el sistema recupera todos los recursos asignados a los procesos terminados.
1 ) Abortar todos los procesos interbloqueados. Esta es una de las soluciones más comunes, adoptada por Sistemas Operativos. Este método romperá definitivamente el ciclo de interbloqueo pero con un costo muy elevado, ya que estos procesos efectuaron cálculos durante mucho tiempo y habrá que descartar los resultados de estos cálculos parciales, para quizá tener que volver a calcularlos más tarde.
2 ) Abortar un proceso en cada ocasión hasta eliminar el ciclo de interbloqueo. El orden en que se seleccionan los procesos para abortarlos debe basarse en algún criterio de costo mínimo. Después de cada aborto, debe solicitarse de nuevo el algoritmo de detección, para ver si todavía existe el interbloqueo. Este método cae enmucho tiempo de procesamiento adicional.
Quizá no sea fácil abortar un proceso. Si éste se encuentra actualizando un archivo, cortarlo a la mitad de la operación puede ocasionar que el archivo quede en un mal estado.
Si se utiliza el método de terminación parcial, entonces, dado un conjunto de procesos bloqueados, debemos determinar cuál proceso o procesos debe terminarse para intentar romper el interbloqueo. Se trata sobre todo de una cuestión económica, debemos abortar los procesos que nos representen el menor costo posible. Existen muchos factores que determinan el proceso que se seleccionará, siendo los principales los siguientes:
La prioridad del proceso. Se elimina el proceso de menor prioridad. Tiempo de procesador usado. Se abortará aquel proceso que haya utilizado menos tiempo el procesador, ya que se pierde menos trabajo y será más fácil recuperarlo más tarde. Tipos de recursos utilizados. Si los recursos son muy necesarios y escasos será preferible liberarlos cuanto antes. Cuántos recursos más necesita el proceso. Es conveniente eliminar a aquellos procesos que necesitan un gran número de recursos. Facilidad de suspensión / reanudación. Se eliminarán aquellos procesos cuyo trabajo perdido sea más fácil de recuperar.
Apropiación de Recursos
Para eliminar interbloqueos utilizando la apropiación de recursos, vamos quitando sucesivamente recursos de los procesos y los asignamos a otros hasta romper el ciclo de interbloqueo.
Si se utiliza la apropiación de recursos para tratar los interbloqueos, hay que considerar tres aspectos:
- Selección de la víctima
- Retroceso
- Bloqueo indefinido
La detección y recuperación es la estrategia que a menudo se utiliza en grandes computadoras, especialmente sistemas por lote en los que la eliminación de un proceso y después su reiniciación suele aceptarse.
Una estrategia integrada de interbloqueo
Puede ser mas eficiente usar diferente estrategias en diferentes situaciones, una de ellas sugiere lo siguiente:
- Agrupar los recursos en un numero de clases diferentes.
- Usar la estrategia de ordenación lineal definida anteriomente para la prevención de circulo viciosos de espera e impedir el interbloqueo entre clases de recursos.
- Dentro de cada clase de recursos, emplear el algoritmo mas apropiado para dicha clase.
Como ejemplo de esta técnica, considérense las siguientes clases de recursos:
- Espacio intercambiable: bloques de memoria en almacenamiento secundario para el intercambio de procesos.
- Recursos de procesos: dispositivos asignables, como unidades de cintas y archivos.
- Memoria principal: asignable a los procesos en paginas o segmentos.
- Recursos internos: como canales de E / S.
El orden en que se encuentran estas clases de recursos es el orden en que se asignan. El orden es razonable, teniendo en cuenta la secuencias de pasos que un proceso debe seguir durante su vida.
En cada clase se pueden usar las siguientes estrategias :
- Espacio Intercambiable: puede aplicarse la prevención de interbloqueos, pidiendo que todos los recursos sean asignados de una vez, como la estrategia de prevención de retención y espera. Esta estrategia es razonable si se conoce los requisitos máximo de almacenamiento, lo que suele ser habitual. Otra posibilidad es la predicción de interbloqueos.
- Recursos de Procesos: la predicción es a menudo efectiva en esta categoría, puesto que es razonable esperar que los procesos declaren por anticipados los recursos de esta clase que necesitaran. También es posible en esta clase la prevención mediante la ordenación de recursos.
- Memoria Principal: la prevención por apropiación parece ser la estrategia mas adecuada para la memoria principal. Cuando se expulsa un proceso, simplemente es trasladado a la memoria secundaria
- Recursos Internos: puede usarse la prevención por ordenación de recursos.
El problema de la cena de los filosofos
Había una vez cinco filósofos que vivían juntos. La vida de cada filósofo consistía principalmente en pensar y comer y, tras años de pensar, todos los filósofos se habían puesto de acuerdo en que la única comida que contribuía a sus esfuerzos eran los espaguetis.
Los preparativos de la comida eran simples : una mesa redonda en la que había una gran fuente de espaguetis, cinco platos, uno para cada filósofo y cinco tenedores. Un filósofo que quisiera comer iría a su lugar asignado en la mesa y, usando los dos tenedores de cada lado del plato, cogería los espaguetis y se los comería. El problema es lo siguiente : inventar un ritual (algoritmo) que permita comer a los filósofos. El algoritmo debe satisfacer la exclusión mutua (dos filósofos no pueden emplear el mismo tenedor a la vez), además de evitar el interbloqueo y la inanición (en este caso, este ultimo termino tiene un significado literal además del algorítmico).
Este problema, propuesto por Dijkstra, puede no parecer importante o relevante por si mismo. Sin embargo, sirve para ilustrar los problemas básicos del interbloqueo y la inanición. Es más, intentar desarrollar una solución revela muchas de las dificultades de la programación concurrente. Además, el problema de la cena de los filósofos puede verse como un caso representativo de los problemas relacionados con la coordinación sobre recursos compartidos, que se produce cuando una aplicación incluye hilos de ejecución concurrentes. Por consiguiente, este problema es un caso de prueba estándar para examinar soluciones a la sincronización.
Una primera solución al problema de la cena de los filósofos es:
/* program cena_filósofos */
semáforo tenedor[5] = {1};
int i;
void filosofo(int i)
{
while (cierto)
{
pensar ( );
wait (tenedor [i]);
wait (tenedor [(i + 1)mod 5];
comer ( );
signal (tenedor [(i + 1) mod 5]);
wait (tenedor [1]);
}
}
void main ( )
{
parbegin (filosofo (0), filosofo (1), filosofo (2), filosofo (3), filosofo (4));
}
Sugiere una solución por medio de semáforos. Cada filosofo toma 1º el tenedor de su izquierda , y después el de su derecha. Cuando un filosofo termina de comer, devuelve los dos tenedores a la mesa. Esta solución, desafortunadamente, produce ínterbloqueo: si todos los filósofos están hambriento al mismo tiempo, todos se sientan, todos toman el tenedor de su izquierda y todos intentan tomar el otro tenedor que no estará. Esta solución es poco decorosa, pues todos los filósofos pasan hambre.-
Para superar el riesgo de ínter bloqueo se podrían adquirir 5 tenedores adicionales ( una solución mas saludable), o enseñar a los filósofos a comer espaguetis con un solo tenedor.
Como otra solución posible , se podría considerar incorporar un sirviente que permita pasar solo a 4 cuatro filósofos a la vez al comedor. Con un máximo de 4 filósofos sentados, al menos uno de los filósofos tendrá acceso a los dos tenedores. En esta figura se muestra con semáforos. Esta solución esta libre de ínter bloqueo e inanición.
/* program cena_filósofos */
semáforo tenedor[5] = {1};
semáforo habitación = {4};
int i;
void filosofo (int i)
{
while (cierto)
pensar ( );
wait (habitación);
wait (tenedor [i]);
wait (tenedor [(i + 1) mod 5]);
comer ( );
signal (tenedor [(i +1) mod 5]);
wait (tenedor [i]);
signal (habitación);
}
void main ( )
{
parbegin (filosofo (0), filosofo (1), filosofo (2), filosofo (3), filosofo (4));
}