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;