Contrastando os algoritmos de Peterson e Dekker

41

Estou tentando entender os algoritmos de Peterson e Dekker que são muito semelhantes e exibem muitas simetrias.

Tentei formular os algoritmos em linguagem informal da seguinte maneira:

Peterson's: "I want to enter."                 flag[0]=true;
            "You can enter next."              turn=1;
            "If you want to enter and          while(flag[1]==true&&turn==1){
            it's your turn I'll wait."         }
            Else: Enter CS!                    // CS
            "I don't want to enter any more."  flag[0]=false;

Dekker's:   "I want to enter."                 flag[0]=true;
            "If you want to enter              while(flag[1]==true){
             and if it's your turn               if(turn!=0){
             I don't want to enter any more."      flag[0]=false;
            "If it's your turn                     while(turn!=0){
             I'll wait."                           }
            "I want to enter."                     flag[0]=true;
                                                 }
                                               }
            Enter CS!                          // CS
            "You can enter next."              turn=1;
            "I don't want to enter any more."  flag[0]=false;

A diferença parece ser o ponto em que "You can enter next."ocorre e o fato que "if it's your turn I don't want to enter any more."ocorre no de Dekker.

No algoritmo de Peterson, os dois processos parecem ser dominantes. Um processo parece forçar a entrada na seção crítica, a menos que seja a vez do outro.

Inversamente, no algoritmo de Dekker, os dois processos parecem submissos e educados. Se os dois processos quiserem entrar na seção crítica, e é a vez do outro, o processo decide não querer mais entrar. (Isso é necessário para a liberdade da fome? Por que?)

Como exatamente esses algoritmos diferem? Imagino que, quando os dois processos tentam entrar na seção crítica, na Peterson, o processo diz "eu entro", enquanto na de Dekker o processo diz "Você pode entrar". Alguém pode esclarecer a maneira como os processos se comportam em cada algoritmo? Minha maneira de colocá-lo em termos informais está correta?

gbag
fonte
Observe que o algoritmo de Peterson não resolve completamente o problema crítico da seção, pois as leituras e gravações nos próprios sinalizadores são problemas críticos da seção. Um artigo que realmente resolve o problema completamente é "O Árbitro: um Componente Ativo do Sistema para Implementar Primitivas de Sincronização", de Henk JM Goeman.
user3083171

Respostas:

24

Suas descrições informais dos algoritmos são maravilhosas.

Penso que nos dois casos o autor estava tentando encontrar a solução mais simples possível, que garantisse exclusão mútua e liberdade de impasse. Nenhum algoritmo é livre de fome ou justo.[ed: como apontado nos comentários, o algoritmo de Peterson é livre de fome e justo]. A solução de Dekker foi o primeiro algoritmo de exclusão mútua usando apenas instruções de carregamento e armazenamento. Foi introduzido em Dijkstra, Edsger W .; "Cooperating sequential process", em F. Genuys, ed., Programming Languages: NATO Advanced Study Institute , pp. 43-112, Academic Press, 1968 . Se você ler o documento, verá Dijkstra trabalhando várias tentativas, reconhecendo o problema de cada uma delas e adicionando um pouco mais para a próxima versão. Parte da ineficiência de seu algoritmo vem do fato de ele começar com um algoritmo de turn-turn e depois tentar modificá-lo para permitir que os processos progridam em qualquer ordem. (Não apenas 0,1,0,1, ...)

O algoritmo de Peterson foi publicado em 1981, após mais de uma década de experiência e retrospectiva sobre o algoritmo de Dekker. Peterson queria um algoritmo muito mais simples que o Dekker, para que a prova de correção seja muito mais fácil. Você pode ver que ele estava sentindo alguma frustração com a comunidade pelo título de seu artigo. Peterson, GL; "Mitos sobre o problema da exclusão mútua", Inf. Proc. Lett. , 12 (3): 115-116, 1981. Leitura muito rápida e muito bem escrita. (E as observações maliciosas sobre métodos formais não têm preço.) O artigo de Peterson também discute o processo pelo qual ele construiu sua solução a partir de tentativas mais simples. (Como a solução é mais simples, foram necessárias menos etapas intermediárias.) Observe que a principal diferença (o que você chama de "dominância" em vez de "submissão") é que, porque Peterson começou de novo (não pelo algoritmo de turno que Dijkstra começou com ) seu loop de espera é mais simples e mais eficiente. Ele percebe que pode se safar com testes simples em loop, enquanto Dijkstra teve que recuar e tentar novamente a cada vez.

Acho que devo mencionar também o clássico artigo sobre o algoritmo Bakery de Lamport : Lamport, Leslie; "Uma nova solução do problema de programação simultânea de Dijkstra", Comm ACM 17 (8): 453-455, 1974 . O algoritmo Bakery é sem dúvida mais simples que o algoritmo de Dekker (e certamente mais simples no caso de mais de 2 processadores) e foi projetado especificamente para tolerar falhas. Eu o mencionei especificamente por duas razões. Primeiro, porque fornece um pouco de história sobre a definição do problema de exclusão mútua e tenta resolvê-lo até 1974. Segundo, porque o algoritmo Bakery demonstra que nenhuma atomicidade de hardware é necessária para resolver o problema de exclusão mútua.

Finalmente, um dos meus favoritos em particular é Lamport, Leslie; "Um algoritmo de exclusão mútua rápida", ACM Trans. Comp. Sys. , 5 (1): 1-11, 1987. Neste artigo, Lamport estava tentando otimizar uma solução para o problema de exclusão mútua no caso (comum) de que há pouca contenção para a seção crítica. Mais uma vez, garante exclusão mútua e liberdade de impasse, mas não justiça. É (acredito) o primeiro algoritmo de exclusão mútua usando apenas leituras e gravações normais que podem sincronizar N processadores no tempo O (1) quando não há contenção. (Quando há contenção, ele recorre a um teste O (N).) Ele dá uma demonstração informal de que o melhor que você pode fazer no caso livre de contenção são sete acessos à memória. (Dekker e Peterson fazem isso com 4, mas eles só podem manipular 2 processadores, quando você estende seus algoritmos para N, eles precisam adicionar um acesso extra de O (N).)

Ao todo: eu diria que o próprio algoritmo de Dekker é interessante principalmente de uma perspectiva histórica. O artigo de Dijkstra explicou a importância do problema de exclusão mútua e demonstrou que ele poderia ser resolvido. Mas, com muitos anos de retrospectiva, foram encontradas soluções mais simples (e mais eficientes) do que as de Dekker.

Lógica Errante
fonte
3
>> Nenhum algoritmo é livre de fome ou justo. Isso não é verdade. O algoritmo de Peterson é livre de fome e justo. Se um encadeamento estiver na seção crítica e o outro estiver aguardando no loop de espera - o que estiver aguardando entrará no CS em seguida, mesmo se o encadeamento que estava no CS for muito mais rápido.
Gostaria de enfatizar que o algoritmo de Peterson é livre de fome e justo , apenas para repetir o comentário de user24190. Não consigo entender por que, depois de todos esses anos, o autor desta resposta não respondeu ao comentário nem corrigiu sua resposta. (não se esqueça de me pingar depois de ter corrigido a resposta para que eu possa remover este comentário meu.)
Apass.Jack
Link para comprar "Mitos sobre o problema de exclusão mútua" de Peterson: doi.org/10.1016/0020-0190(81)90106-X
strager
PDF de Peterson de "Mitos sobre o problema de exclusão mútua" (Archive.org): web.archive.org/web/20150501155424/https://cs.nyu.edu/~lerner/...
strager
3

No artigo a seguir, apresentamos modelos formais para os algoritmos de Peterson e Dekker (e alguns outros) e usamos o verificador de modelos para provar suas propriedades. Por favor, encontre nossos resultados na tabela abaixo (as colunas "Impasse" e "Divergente" se referem aos nossos modelos, "ME" = VERDADEIRO significa que o algoritmo está correto, "Ultrapassagem" = VERDADEIRO significa que é justo).

R. Meolic, T. Kapus, Z. Brezočnik. ACTLW - Uma lógica de árvore de computação baseada em ação, a menos que o operador. Ciência da Informação, 178 (6), pp. 1542-1557, 2008.

https://doi.org/10.1016/j.ins.2007.10.023

insira a descrição da imagem aqui

meólico
fonte
1

O algoritmo de Peterson exerce uma pressão mais estrita ao entrar na seção crítica, onde o algoritmo de Dekker é relativamente mais suave e menos agressivo. Para deixar mais claro, vejamos um exemplo sobre a cultura iraniana. Antes de entrar neste exemplo, é bom saber que as pessoas iranianas têm um comportamento muito suave quando entram em algum lugar! Acho que dois homens iranianos vão entrar em uma casa, e essa casa tem apenas uma porta para entrar.

Agora imagine dois homens de outra cultura ( Cultura Zombiana ), na qual eles não se importam muito um com o outro enquanto entram em algum lugar ( é uma questão de respeito perguntar a alguém se ele quer entrar ou não ).

Para esclarecer as informações sobre o problema, podemos dizer que:

  • Dois iranianos = dois processos usando o algoritmo Dekker
  • Dois zumbis = dois processos usando o algoritmo Peterson

Então, vamos descobrir o que é feito em cada algoritmo ( cultura ). Os comentários a seguir são para o primeiro iraniano que entra na casa enquanto usa o algoritmo Dekker :

p0:
   wants_to_enter[0] ← true // Goes through the house entrance
   while wants_to_enter[1] { // If the other man wants to enter too
      if turn ≠ 0 { // Then see if it is your turn or not
         wants_to_enter[0] ← false // If it is not your turn don't go furthur
         while turn ≠ 0 { // and wait until it is your turn
           // busy wait
         }
         wants_to_enter[0] ← true // when it is your turn go through the door
      }
   }

   // critical section
   ...
   turn ← 1
   wants_to_enter[0] ← false // Set the turn for the other man
   // remainder section

Também temos dois zumbis que entrarão na casa usando o algoritmo Peterson . Este é o seguinte:

P0:     
  flag[0] = true; // Goes through the house entrance
  turn = 1; // Set the turn for himself
  while (flag[1] && turn == 1) // Wait until the other one is going in
  {
   // busy wait
  }
   // critical section
      ...
   // end of critical section
  flag[0] = false; // Done going inside

É importante mencionar que os dois não estão entrando enquanto o outro está fazendo isso ( exclusão mútua ), mas o povo iraniano é muito mais suave.

hexfeu
fonte