Download - O Problema da Exclusão Mútua
O Problema da Exclusão Mútua
Eduardo Nicola F. Zagari
Principles of Concurrent and Distributed Programming - Ben-Ari
Tópicos
• Introdução• Primeira Tentativa• Segunda Tentativa• Terceira Tentativa• Quarta Tentativa• Algoritmo de Dekker• Exclusão Mútua para N Processos• Exclusão Mútua Assistida por Hardware
Introdução
• O problema da Exclusão Mútua para N processos:
1. N processos executando laços infinitos de instruções: regiões críticas (RC) e regiões não críticas (RNC). O programa deve satisfazer a propriedade de exclusão mútua (não intercalamento das regiões críticas)
2. A solução será descrita pela adição de um pré e um pós-protocolo executado pelo processo que deseja entrar/sair da RC
Introdução
Forma da Solução de Exclusão Mútua
LoopRegião Não Crítica;Pré-Protocolo;Região Crítica;Pós-Protocolo;
End loop;
Introdução
3. Um processo pode parar em sua RNC (neste caso, ele não deve interferir nos outros), mas não pode parar durante a execução dos protocolos nem da RC
4. Os processos não devem provocar bloqueio (deadlock) na tentativa de acessar suas RCs
5. Não deve haver inanição (starvation) de nenhum dos processos
6. No caso de não haver disputa pelo acesso à RC, o processo deve ser bem sucedido e com overhead mínimo
Primeira Tentativa
task body P1 isbegin loop Regiao_Nao_Critica_1; loop exit when Turn = 1; end loop; Regiao_Critica_1; Turn := 2; end loop;end P1;
task body P2 isbegin loop Regiao_Nao_Critica_2; loop exit when Turn = 2; end loop; Regiao_Critica_2; Turn := 1; end loop;end P2;
Turn: Integer range 1..2 := 1;
Primeira Tentativa
• Esta solução satisfaz os requisito de exclusão mútua
• A solução não causa deadlock
• Não há starvation
• Mas... A solução pode falhar no caso de ausência de disputa...
Segunda Tentativa
task body P1 isbegin loop Regiao_Nao_Critica_1; loop exit when C2 = 1; end loop; C1 := 0; Regiao_Critica_1; C1 := 1; end loop;end P1;
task body P2 isbegin loop Regiao_Nao_Critica_2; loop exit when C1 = 1; end loop; C2 := 0; Regiao_Critica_2; C2 := 1; end loop;end P2;
C1, C2: Integer range 0..1 := 1;
Segunda Tentativa
• Considere:– P1 verifica C2 e encontra C2 = 1– P2 verifica C1 e encontra C1 = 1– P1 ajusta C1 para 0– P2 ajusta C2 para 0– P1 entra na sua região crítica– P2 entra na sua região crítica
• Ou seja, nem mesmo o requisito básico de exclusão mútua é satisfeito...
Terceira Tentativa
task body P1 isbegin loop Regiao_Nao_Critica_1; C1 := 0; loop exit when C2 = 1; end loop; Regiao_Critica_1; C1 := 1; end loop;end P1;
task body P2 isbegin loop Regiao_Nao_Critica_2; C2 := 0; loop exit when C1 = 1; end loop; Regiao_Critica_2; C2 := 1; end loop;end P2;
C1, C2: Integer range 0..1 := 1;
Terceira Tentativa
• A solução satisfaz a propriedade de exclusão mútua
• Mas... Considere:– P1 atribui 0 para C1– P2 atribui 0 para C2– P1 testa C2 e permanece no loop– P2 testa C1 e permanece no loop...– Ou seja, deadlock...
Quarta Tentativa
task body P1 isbegin loop Regiao_Nao_Critica_1; C1 := 0; loop exit when C2 = 1; C1 := 1; C1 := 0; end loop; Regiao_Critica_1; C1 := 1; end loop;end P1;
task body P2 isbegin loop Regiao_Nao_Critica_2; C2 := 0; loop exit when C1 = 1; C2 := 1; C2 := 0; end loop; Regiao_Critica_2; C2 := 1; end loop;end P2;
C1, C2: Integer range 0..1 := 1;
Quarta Tentativa
• A solução satisfaz a propriedade de exclusão mútua• Mas...Um processo pode sofrer starvation! Considere:
– P1 atribui 0 para C1– P2 atribui 0 para C2– P2 testa C1 e então reseta C2 para 1– P1 executa o ciclo completo:
• Verifica C2• Entra na RC• Reseta C1• Executa sua RNC• Ajusta C1 para 0
– P2 atribui 0 para C2... Ou seja, voltamos ao início... Starvation de P2.
Quarta Tentativa
• A solução pode ainda provocar uma “forma” de deadlock: o livelock (situação em que até que existe possibilidade de sucesso, mas pode acontecer dos 2 nunca conseguirem entrar na RC!). Exemplo:– P1 ajusta C1 para 0– P2 ajusta C2 para 0– P1 verifica C2 e permanece em loop– P2 verifica C1 e permanece em loop– P1 reseta C1 para 1– P2 reseta C2 para 1– P1 ajusta C1 para 0– P2 ajusta C2 para 0– P1 verifica C2 e permanece em loop– P2 verifica C1 e permanece em loop...
Algoritmo de Dekker
task body P1 isbegin loop Regiao_Nao_Critica_1; C1 := 0; loop exit when C2 = 1; if Turn = 2 then C1 := 1; loop exit when Turn = 1; end loop; C1 := 0; end if; end loop; Regiao_Critica_1; C1 := 1; Turn := 2; end loop;end P1;
C1, C2: Integer range 0..1 := 1;Turn: Integer range 1..2 := 1;
task body P2 isbegin loop Regiao_Nao_Critica_2; C2 := 0; loop exit when C1 = 1; if Turn = 1 then C2 := 1; loop exit when Turn = 2; end loop; C2 := 0; end if; end loop; Regiao_Critica_2; C2 := 1; Turn := 1; end loop;end P2;
Algoritmo de Dekker
• Satisfaz a propriedade de exclusão mútua
• Não provoca deadlock
• Nenhum processo pode sofrer starvation
• Na falta de disputa pela RC, um processo pode entrar em sua região crítica imediatamente
Exclusão Mútua para N processosO Algoritmo da Padaria
task body P1 isbegin loop Regiao_Nao_Critica_1; N1 := 1; N1 := N2 + 1; loop exit when
N2 = 0 or N1 <= N2; end loop; Regiao_Critica_1; N1 := 0; end loop;end P1;
task body P2 isbegin loop Regiao_Nao_Critica_2; N2 := 1; N2 := N1 + 1; loop exit when
N1 = 0 or N2 < N1; end loop; Regiao_Critica_2; N2 := 0; end loop;end P2;
N1, N2: Integer range 0..1 := 0;
Para 2 processosPara 2 processos
Exclusão Mútua para N processosO Algoritmo da Padaria
task body Pi is I: constant Integer := ...; /* Task id */begin loop Regiao_Nao_Critica_I; Escolhendo(I) := 1; Number(I) := 1 + max(Number); Escolhendo(I) := 0; for J in 1..N loop if J != I then loop exit when Escolhendo(J) = 0; end loop; loop exit when Number(J) = 0 or Number(I) < Number(J) or (Number(I) = Number(J) and I < J); end loop; end if; end loop; Regiao_Critica_I; Number(I) := 0; end loop;end Pi;
Escolhendo: array(1..N) of Integer := (others => 0);Number: array(1..N) of Integer := (others => 0);
Para N processosPara N processos
Exclusão Mútua Assistida por Hardware
• Dificuldade em se obter exclusão mútua através de instruções que podem ser intercaladas
• Instruções Atômicas– Test and Set– Exchange
Exclusão Mútua Assistida por Hardware
Li := C;C := 1;
task body Pi is Li: Integer range 0..1;begin loop Regiao_Nao_Critica_i; loop Test_and_Set(Li); exit when Li = 0; end loop; Regiao_Critica_i; C := 0; end loop;end Pi;
Para N processosPara N processosInstrução Test_and_Set(Li) :Instrução Test_and_Set(Li) :
C: Integer range 0..1 := 0;
Exclusão Mútua Assistida por Hardware
Temp := A;A := B;B := Temp;
task body Pi is Li: Integer range 0..1 := 0;begin loop Regiao_Nao_Critica_i; loop Exchange(C,Li); exit when Li = 1; end loop; Regiao_Critica_i; Exchange(C,Li); end loop;end Pi;
Para N processosPara N processosInstrução Exchange(A,B) :Instrução Exchange(A,B) :
C: Integer range 0..1 := 1;