Coordinación entre Procesos Parte I Contenido

Anuncio
Contenido
Coordinación entre Procesos
Parte I
• Semáforo: mecanísmo de bajo nivel para la
sincronización de procesos
– Operaciones
– Implementación
– Ejemplos: Filósofos, Lectores-Escritores
– Limitaciones
• Monitor: mecanísmo de alto nivel para la
sincronización de procesos
M. B. Ibáñez
M. B. Ibáñez
Requerimientos para los
Mecanismos de Sincronización
Tipo de Dato Semáforo
• Deben permitir tan solo un poceso a la vez dentro
de una región crítica
• Si se realizan varias peticiones a la vez, solo un
proceso puede tener acceso a la región crítica
• Si varios procesos esperan, cada uno de ellos
entrará eventualmente a la región crítica
• No usar los recursos mientras se está dentro de la
región crítica
• Debe ser fácil de usar
WAIT(semaphore)
Interface
operators
SIGNAL(semaphore)
M. B. Ibáñez
Uso de los Semáforos
Exclusión Mutua
var s: semaphore;
s.count = s.count - 1
if s.count < 0 then {
coloque el proceso en
s.queue
bloquee este proceso
}
SIGNAL(s)
s.count = s.count + 1
if s.count ≤ 0 then {
remueva el proceso de
s.queue
coloque el proceso en
la cola “ready”
}
count
Queue pointer
M. B. Ibáñez
Semántica de las Operaciones
WAIT(s)
Representation of
a semaphore
var data-structure: some-type;
lock: semaphore = 1;
procedure access-shared-data {
<non-critical instructions>
WAIT(lock);
<access shared-data-structure>
SIGNAL(lock);
<non-critical instructions>
}
M. B. Ibáñez
M. B. Ibáñez
1
Uso de los Semáforos
Uso de los Semáforos
Sincronización de Procesos Cooperantes
Múltiples instancias de un recurso
Sean los procesos P1 = {S1} y P2 = {S2}
Se quiere ejecutar S2 solo después de haber
concluido S1
var synch: semaphore = 0;
procedure P1 {S1; signal(synch)}
procedure P2 {wait(synch); S2}
var s: semaphore = N;
procedure usar-recurso{ wait(s);}
procedure liberar-recurso{ signal(s);}
M. B. Ibáñez
M. B. Ibáñez
Uso de los Semáforos
Buffer de capacidad limitada I
Buffer de capacidad limitada II
Producer: Crea items
Consumer: Utiliza (destruye) items
Buffer:
Capacidad para N items
• Solo un proceso a la vez puede usar el buffer
• Los consumidores no pueden tomar items del
buffer cuando éste está vacío
• Los productores no pueden añadir items al buffer
cuando éste está lleno
M. B. Ibáñez
El productor añade items al buffer
var empty_spaces:
semaphore = N;
procedure producer {
while(true){
produce_item();
wait(empty_spaces);
put_item_into_buffer();
}
}
procedure consumer {
while(true) {
consume_item();
signal(empty_spaces);
}
}
M. B. Ibáñez
Buffer de capacidad limitada III
Buffer de capacidad limitada IV
El consumidor toma items del buffer
Productor y Consumidor comparten el buffer
var
full_spaces: semaphore = 0;
procedure producer {
while(true){
produce_item();
signal(full_spaces);
}
}
procedure consumer {
while(true) {
wait(full_spaces);
consume_item();
}
}
M. B. Ibáñez
var mutex: semaphore = 1;
procedure producer {
while(true){
produce_item();
wait(mutex);
put_item_into_buffer();
signal(mutex);
}
}
procedure consumer {
while(true) {
wait(mutex);
take_item_from_buffer();
signal(mutex);
consume_item();
}
}
M. B. Ibáñez
2
Buffer de capacidad limitada V
El problema de los filósofos
procedure consumer {
while(true) {
wait(full_spaces);
wait(mutex);
take_item_from_buffer();
signal(mutex);
signal(empty_spaces);
consume_item();
}
}
procedure producer {
while(true){
produce_item();
wait(empty_spaces);
wait(mutex);
put_item_into_buffer();
signal(mutex);
signal(full_spaces);
}
}
M. B. Ibáñez
M. B. Ibáñez
Primer intento
Definiciones
var fork: array[0..4] of semaphore; /* all elements = 1 */
procedure philosopher(i:integer)
repeat
wait(fork[i]);
/* takes left fork
*/
wait(fork[i+1 mod 5]);
/* takes right fork */
<eat>
signal (fork[i]);
/* releases left fork */
signal (fork[i+1 mod 5]);
/* releases right fork */
<think>
until false;
# define N
5
# define LEFTN (i-1)%N
# define RIGHTN (i+1)%N
/* Número de filósofos */
/*Vecino izquierdo del filósofo i */
/*Vecino derecho del filósofo i*/
# define THINKING 0
# define HUNGRY 1
# define EATING
2
/* Estado */
/* Estado */
/* Estado */
M. B. Ibáñez
M. B. Ibáñez
Semáforos
Acciones de los Filósofos
var
state: integer array[N];
mutex: semaphore = 1;
s: semaphore array[N];
/*estado de cada filósofo*/
/* examine el estado de un
solo filósofo cada vez
*/
/* si un filósofo no logra
tomar los tenedores, se
autobloquea */
M. B. Ibáñez
procedure philosopher(i: integer){
while (true) {
state[i] = THINKING;
get_forks(i);
state[i] = EATING;
release_forks(i);
}
M. B. Ibáñez
}
3
procedure get_forks(i: integer)
procedure release_forks(i: integer)
{
wait(mutex); /* Nadie más puede trabajar sobre state */
state[i]= HUNGRY;
/* Quiere los recursos*/
test(i);
/* trata de obtener ambos tenedores */
signal(mutex);
wait(s[i]); /* se bloquea si no obtiene los tendores */
}
{
/* Nadie más puede ttrabajar sobre state */
wait(mutex);
state[i]= THINKING;
/* Ya no necesita los recursos */
test(LEFT);
/* su vecino izquierdo puede comer? */
test(RIGHT);
/* su vecino derecho puede comer? */
signal(mutex);
}
M. B. Ibáñez
M. B. Ibáñez
procedure test(i: integer)
Lectores-Escritores
{if (state[i] == HUNGRY and
state[LEFT] != EATING and
state[RIGHT] != EATING ) {
state[i] = EATING;
signal(s[i]);
}
}
• Un objeto es compartido por varios
procesos concurrentes
• Los lectores solo leen el contenido del
aobjeto compartido
• Los escritores actualizan el objeto
compartido
M. B. Ibáñez
M. B. Ibáñez
Garantizando la exclusión mutua
Variables
var access_db: semaphore = 1;
procedure reader {…}
procedure writer{
…
wait(access_db);
<writing is performed>;
signal(access_db);
...
}
M. B. Ibáñez
var
access_counter: semaphore = 1;
access_db:
semaphore = 1;
n_readers:
integer = 0;
M. B. Ibáñez
4
procedure reader
procedure reader
{while(true){
¿Soy el primer lector?
SI: wait(access_db)
READ
¿Soy el último lector?
NO: signal(access_db)
USE DATA
}
{while(true){
wait(access_counter);
n_readers = n_readers + 1;
/* first reader ? */
if (n_readers == 1) then
wait(access_db);
signal(access_counter);
< read data base > ;
M. B. Ibáñez
M. B. Ibáñez
Limitaciones de los Semáforos
Monitor: Estructura de Datos I
t yp e monitor-name = mon it or
• Es fácil cometer errores.
– No es sencillo recordar qué semáforo está asociado a una
determinada estructura de datos.
– Sería preferible tener una alternativa.
• El tiempo durante el cual un proceso se bloquea
no está limitado.
– Un proceso está bloqueado hasta que alguien lo depierta gracias a
una señal.
•
procedure entry P1(…) {…};
procedure entry P2(…) {…};
...
procedure entry PN(…) {…};
{
< initialization-code >
}
O1
P1
O2
P2
shared data
PN
M. B. Ibáñez
M. B. Ibáñez
Monitor: Estructura de Datos II
Variables de Condición
Solo un proceso a la vez puede
estar activo dentro del monitor
Un procedimiento definido
dentro de un monitor puede
tener acceso a:
– Sus parámetros formales
– Sus variables locales
– Las variables del monitor
•
Monitor
<variable-declar ations>;
• Cuando se examina un recurso y éste está ocupado
el proceso siempre se bloquea
•
wait(access_counter);
n_readers = n_readers - 1;
/* last reader ? */
if (n_readers == 0) then
signal(access_db);
signal(access_counter);
< use data >;
}}
Las variables locales de un
monitor pueden ser utilizadas
solo por los procedimientos
locales
Monitor
P1
O1
O2
process1
process1
P2
process1
shared data
PN
M. B. Ibáñez
var x,y: condition;
• El proceso que invoca
“x.wait;” es suspendido
hasta que otro proceso
invoque “x.signal;”
• La “x.signal;” reasume
exactamente un proceso
suspendido
• Si ningún proceso está
suspendido, la señal no
tiene efecto.
Monitor
P1
O1
O2
process1
process2
P2
shared data
X
process3
Y
PN
process 4
process 5
process 6
M. B. Ibáñez
5
Ejemplo:Asignación de Recursos I
type resource-assignation = monitor
var busy: boolean;
var free: condition;
procedure entry reserve(){...}
procedure entry release(){…}
{
busy := false;
}
Ejemplo: Asignación de Recursos II
procedure entry reserve() {
if busy then free.wait;
busy := true;
}
process use_resource(){
resourceassignation.reserve();
using_resource();
procedure entry release() {
busy := false;
free.signal;
};
resourceassignation.release();
}
M. B. Ibáñez
M. B. Ibáñez
Solución al problema de los
filósofos utilizando Monitores I
Solución al problema de los
filósofos utilizando Monitores II
type dining-philosophers = monitor
var state: array[0..4] of {thinking, hungry, eating};
var self: array[0..4] of condition;
procedure entry pickup(i: 0..4);{…}
procedure entry putdown(i: 0..4);{…}
procedure entry test(k: 0..4);{…}
{
for i := 0 to 4 do
state[i] := thinking;
}
M. B. Ibáñez
procedure entry
pickup(i: 0..4);
{
state[i] := hungry;
test(i);
if state[i] != eating then
self[i].wait;
}
procedure entry
putdown(i: 0..4);
{
state[i] := thinking;
test(i+4 mod 5);
test(i+1 mod 5);
}
M. B. Ibáñez
Solución al problema de los
filósofos utilizando Monitores III
procedure test(k:0..4); {
if state[k+4 mod 5] != eating and
state[k] = hungry and
state[k+1 mod 5] != eating then {
state[k] := eating;
self[k].signal;
}
}
M. B. Ibáñez
6
Descargar