Algoritmos para exclus˜ao mútua Memória - IC

Propaganda
Dekker
Peterson
Algoritmos para exclusão mútua
Memória compartilhada e espera ocupada
Islene Calciolari Garcia
Instituto de Computação - Unicamp
Segundo Semestre de 2011
Dekker
Peterson
Sumário
1
Dekker
2
Peterson
Dekker
Peterson
Algoritmo de Dekker
A primeira solução para exclusão mútua utilizando apenas memória
compartilhada. Sem deadlock e sem starvation.
Wikipédia em inglês: Dekker’s algorithm
Wikipédia em português: ???
Vamos analisar o código por partes...
Dekker
Peterson
Abordagem da Alternância (turn-taking)
int s = 0;
int vez = 1; /* Primeiro a thread 1 */
Thread 0
Thread 1
while (true)
while (vez != 0);
s = 0;
print ("Thr 0:" , s);
vez = 1;
while (true)
while (vez != 1);
s = 1;
print ("Thr 1:" , s);
vez = 0;
Veja o código: alternancia.c
Dekker
Peterson
Vetor de flags
int s = 0;
int flag[2] = {false, false};
Thread 0
Thread 1
while (true)
flag[0] = true;
while (flag[1]);
s = 0;
print("Thr 0:" , s);
flag[0] = false;
while (true)
flag[1] = true;
while (flag[0]);
s = 1;
print("Thr 1:" , s);
flag[1] = false;
Veja o código: flag.c
Dekker
Peterson
Limitações do vetor de flags
O algoritmo anterior garante exclusão mútua, mas...
se as duas threads ficarem interessadas ao mesmo tempo
haverá deadlock.
Podemos tentar sanar este problema da seguinte forma:
Se as duas threads levantarem o flag ao mesmo
tempo, elas irão abaixá-los, esperar um pouco e
tentar novamente.
Veja o código: flag-gentileza.c
Dekker
Peterson
Vetor de flags, com gentileza
int s = 0;
int flag[2] = {false, false};
Thread 0
Thread 1
while (true)
flag[0] = true;
while (flag[1])
flag[0] = false;
sleep(1);
flag[0] = true;
s = 0;
print("Thr 0:" , s);
flag[0] = false;
while (true)
flag[1] = true;
while (flag[0])
flag[1] = false;
sleep(1);
flag[1] = true;
s = 1;
print("Thr 1:" , s);
flag[1] = false;
Dekker
Peterson
Limitações do vetor de flags com gentileza
O algoritmo anterior garante exclusão mútua, mas...
se as duas threads andarem sempre no mesmo passo haverá
livelock.
Podemos tentar outra abordagem que é:
Se as duas threads levantarem o flag ao mesmo
tempo, entrará na região crı́tica a thread cujo
identificador estiver marcado na variável vez.
Veja o código: flag-alternancia.c
Dekker
Peterson
Vetor de Flags e Alternância
int s = 0, vez = 0;
int flag[2] = {false, false};
Thread 0
Thread 1
while (true)
flag[0] = true;
if (flag[1])
while (vez != 0);
s = 0;
print("Thr 0:", s);
vez = 1;
flag[0] = false;
while (true)
flag[1] = true;
if (flag[0])
while (vez != 1);
s = 1;
print("Thr 1:", s);
vez = 0;
flag[1] = false;
Veja o código: flag-alternancia.c
Dekker
Peterson
Limitações de flag-alternancia
Não garante exclusão mútua. Você consegue indicar um
cenário?
Podemos tentar melhorar o algoritmo:
Se as duas threads levantarem o flag ao mesmo
tempo elas deverão abaixá-los e esperar por sua vez.
Veja o código: flag-gentileza-alternancia.c
Dekker
Peterson
Vetor de flags, gentileza e alternância
int s = 0, vez = 0, flag[2] = {false, false};
Thread 0
Thread 1
while (true)
flag[0] = true;
while (flag[1])
flag[0] = false;
while (vez !=0);
flag[0] = true;
s = 0;
print ("Thr 0:" , s);
vez = 1;
flag[0] = false;
while (true)
flag[1] = true;
while(flag[0])
flag[1] = false;
while(vez != 1);
flag[1] = true;
s = 1;
print ("Thr 1:" , s);
vez = 0;
flag[1] = false;
Dekker
Peterson
Limitações do algoritmo anterior
O algoritmo anterior garante exclusão mútua?
É possı́vel que uma thread ganhe sempre a região crı́tica
enquanto a outra fica só esperando?
Podemos melhorar o algoritmo:
Se as duas threads levanarem o flag ao mesmo
tempo, apenas a thread da vez irá abaixá-lo.
Veja o código: dekker.c
Dekker
Peterson
Algoritmo de Dekker
int s = 0, vez = 0, flag[2] = {false, false};
Thread 0
Thread 1
while (true)
flag[0] = true;
while (flag[1])
if (vez != 0)
flag[0] = false;
while (vez !=0);
flag[0] = true;
s = 0;
print ("Thr 0:" , s);
vez = 1;
flag[0] = false;
while (true)
flag[1] = true;
while(flag[0])
if (vez != 1)
flag[1] = false;
while(vez != 1);
flag[1] = true;
s = 1;
print ("Thr 1:" , s);
vez = 0;
flag[1] = false;
Dekker
Peterson
Algoritmo de Petterson (desempate: 1981)
Tão bom quanto Dekker, mas muito mais simples!
Wikipédia em inglês: Peterson’s algorithm
Wikipédia em português: Algoritmo de Peterson
Dekker
Peterson
Algoritmo de Peterson (desempate: 1981)
int s = 0, ultimo = 0, flag[2] = {false, false};
Thread 0
Thread 1
while (true)
flag[0] = true;
ultimo = 0;
while (ultimo == 0 &&
flag[1]);
s = 0;
print ("Thr 0:" , s);
flag[0] = false;
while (true)
flag[1] = true;
ultimo = 1;
while (ultimo == 1 &&
flag[0]);
s = 1;
print ("Thr 1:" , s);
flag[1] = false;
Download