Se eu usar bloqueios, meu algoritmo ainda pode estar livre de bloqueios?

9

Uma definição comum de livre de bloqueio é que pelo menos um processo progride. 1 1

Se eu tiver uma estrutura de dados simples, como uma fila, protegida por um bloqueio, um processo sempre poderá progredir, pois um processo pode adquirir o bloqueio, fazer o que ele deseja e liberá-lo.

Então, ele atende à definição de lock-free?


1 Ver, por exemplo, M. Herlihy, V. Luchangco e M. Moir. Sincronização sem obstruções: Filas de duas extremidades como exemplo. Em Computação Distribuída, 2003. "É livre de bloqueios se garantir apenas que algum encadeamento sempre faça progresso".

Joe Pension
fonte
3
Eu sempre entendi "bloqueio livre" para descrever uma estrutura de dados e um conjunto de algoritmos que não usam bloqueios, apenas um pequeno conjunto definido de operações de memória atômica. Por exemplo, drdobbs.com/parallel/writing-lock-free-code-a-corrected-queue/…
Paul Johnson

Respostas:

16

Essa não é uma definição para livre de bloqueio.

Se você puder garantir o progresso, estará livre de impasse e , se tiver a conclusão final de cada solicitação, estará livre de fome , mas não de bloqueio.

Eu questiono se o seu exemplo simples realmente fornece isso de qualquer maneira. Você precisa de hierarquias de bloqueio e assim por diante para realmente garantir o progresso quando vários bloqueios estiverem envolvidos.

Ben Voigt
fonte
11
Estou usando a definição de M. Herlihy. Uma metodologia para implementar objetos de dados altamente simultâneos. Transações sobre linguagens e sistemas de programação, 1993. "A condição de travamento garante que algum processo sempre progredirá, apesar de falhas de interrupção arbitrárias ou atrasos de outros processos"
Joe Pension
12
@ Joe: Isso não é uma definição, descreve uma implicação. Cuidado com a falácia lógica do inverso.
Ben Voigt
2
Também poderia citar M. Herlihy, V. Luchangco e M. Moir. Sincronização sem obstruções: Filas de duas extremidades como exemplo. Em Computação Distribuída, 2003. "É livre de bloqueios se garantir apenas que algum encadeamento sempre faça progresso".
21412 Joe Pension
11
há também a fome livre que é mais específico do que impasse livre (cada processo tem que ir, não importa o que outros processos fazem) nota que loops de CAS (com base em primitivas atômicas) não são
catraca aberração
5
@ Joe: Se o resto do mundo chama essa propriedade de impasse , então eu vou usar esse termo. Não, seu exemplo simples não está livre de impasse. Para garantir que algo esteja livre de impasse, você não precisa apenas de sincronização, mas também uma garantia de que nenhum encadeamento execute qualquer operação de bloqueio enquanto mantém o bloqueio. "faça o que quiser" é extremamente vago e não parece fornecer essa garantia.
Ben Voigt
11

Estudei The Art of Multiprocessor Programming 1 e seu texto está faltando em clareza, assim como o livro a que você se refere. Aqui estão algumas citações do TAMPP:

Citação 1 (Definição de bloqueio)

Um método é livre de bloqueios se garantir que infinitamente muitas vezes alguma chamada de método seja concluída em um número finito de etapas.

Citação 2 (Definição de não bloqueio)

uma invocação pendente de um método total nunca é necessária para aguardar a conclusão de outra invocação pendente.

Citação 3 (alegar que o bloqueio é livre de bloqueio)

As condições de progresso sem bloqueio e sem espera e sem bloqueio garantem que o cálculo como um todo progrida, independentemente de como o sistema agende os encadeamentos.

O problema é que a alegação na citação 3 obviamente não segue a definição da citação 1. Como já mencionado, uma fila sincronizada parece satisfazer a citação 1: infinitamente, com frequência, algum método obtém com êxito o bloqueio e é concluído.

Observe especificamente a frase bastante vaga da citação 3: "independentemente de como o sistema agende os threads". Isso não é precedido por nenhum tipo de descrição formal do "sistema de agendamento de encadeamentos"; portanto, resta reconstruir suas propriedades com base em nossos preconceitos sobre o que as definições devem significar:

  1. o sistema sempre executa instruções de algum encadeamento;
  2. ele nunca pode executar instruções de qualquer dado fio;
  3. todos os threads estão invocando o método em consideração.

Nesse sistema, um método de bloqueio não pode ser livre de bloqueios: se o encadeamento que segura o trava nunca for agendado novamente para execução, não haverá outro encadeamento que possa concluir sua invocação de método em um número finito de etapas, mas haverá alguns segmentos que estão executando etapas do método. Para um sistema mais realista, que garanta tempo de CPU para cada thread eventualmente, a definição deve incluir explicitamente a propriedade nonblocking:

Definição corrigida de livre de bloqueio

Um método é livre de bloqueios se não for bloqueador e, além disso, garante que infinitamente muitas vezes alguma chamada de método seja concluída em um número finito de etapas.

1 Maurice Herlihy, Nir Shavit, A Arte da Programação em Multiprocessador, Elsevier 2008, pp. 58-60

Marko Topolnik
fonte
11
A redação da citação 1 é realmente estranha. O que eles querem dizer com "infinitamente frequentemente"? Obviamente, algo diferente de "sempre", então está tudo bem que o método nunca retorne em "alguns" casos?
Hulk
Sim, a linguagem imprecisa é abundante. O que é "frequentemente", afinal? Eu acho que eles significam "em uma história de execução infinita, esse evento em particular ocorre infinitamente várias vezes".
Marko Topolnik
5

A terminologia nem sempre é consistente, mas acho que é importante fazer as seguintes perguntas sobre um algoritmo ou sistema proposto:

  1. Existe alguma sequência de eventos em que os threads possam ficar presos esperando um pelo outro, mesmo que todos os threads tenham tempo de CPU suficiente para usar [nesse caso, não há impasse]
  2. Se um encadeamento foi bloqueado por um longo período de tempo arbitrário, isso poderia interromper outros encadeamentos ou prejudicar a operação do sistema por um longo tempo arbitrariamente [se assim for, não é sem bloqueio].
  3. Existe alguma combinação pelo menos teoricamente possível de agendamento de encadeamentos que poderia fazer com que todos os encadeamentos repetissem as mesmas operações repetidamente, invalidando o trabalho uns dos outros, sem que ninguém progredisse [nesse caso, não é livre de bloqueios]
  4. Se alguns segmentos tiverem tempo de CPU suficiente em relação a outro, eles poderiam forçar o último segmento a continuar repetindo suas operações indefinidamente [nesse caso, não é sem espera].

Muito do significado dos algoritmos sem bloqueio não é que eles são mais rápidos do que os algoritmos sem bloqueio, mas o fato de que eles não são propensos a morrer se um encadeamento for desviado [observe que essa garantia apenas exige que os algoritmos não bloqueiam, mas todos os algoritmos sem bloqueios são]. É possível que um algoritmo sem bloqueios use bloqueios, mas somente se as tentativas de aquisição de bloqueios incluírem tempos limites, juntamente com algoritmos, para garantir que sempre seja possível alguém progredir (por exemplo, um algoritmo pode usar um CompareExchangeloop como principal) método de arbitragem, mas use bloqueios para arbitrar o acesso quando a contenção parecer alta; se um bloqueio parecer mantido excessivamente longo, outros threads poderão decidir abandonar os esforços para usá-lo e criar um novo.CompareExchange, fazer com que os clientes abandonem o bloqueio não comprometeria a consistência do sistema, embora isso possa significar que o código que estava mantendo o bloqueio antigo não será executado até que abandone o bloqueio antigo e se alinhe ao novo.

supercat
fonte
Isso é diferente da terminologia padrão: o seu 2. refere-se ao significado padrão de não-bloqueio, enquanto o 3. refere-se à liberdade de bloqueio.
Marko Topolnik
Vi usos terminológicos inconsistentes e não conheço um padrão "oficial". O mais importante é que existem garantias diferentes que um algoritmo pode oferecer, e é importante usar um algoritmo que ofereça garantias suficientes para atender aos requisitos do aplicativo. Muitos documentos cobrem apenas algumas das garantias acima, mas há casos em que cada um deles pode atender aos requisitos de aplicação mais facilmente do que qualquer outra garantia que atenda aos requisitos.
Supercat
Eu acho que há um consenso de que a terminologia apresentada em The Art of Multiprocessor Programming é "padrão".
Marko Topolnik
@ MarkoTopolnik: Vou editar o post para caber nesse momento. Você gosta da nova versão?
supercat
Legal, muito legal.
Marko Topolnik
4

Você precisa observar a "definição" citada no contexto :

A maneira tradicional de implementar estruturas de dados compartilhadas é usar exclusão mútua (bloqueios) para garantir que operações simultâneas não interfiram entre si. O bloqueio tem várias desvantagens em relação à engenharia de software, tolerância a falhas e escalabilidade (consulte [8]). Em resposta, os pesquisadores investigaram uma variedade de técnicas alternativas de sincronização que não empregam exclusão mútua . Uma técnica de sincronização fica livre de espera se garantir que todos os encadeamentos continuarão progredindo diante de atraso arbitrário (ou até falha) de outros encadeamentos. É livre de bloqueio se garantir apenas que algum encadeamento sempre progrida.

Você está usando bloqueios para exclusão mútua, portanto, não é uma técnica sem bloqueios sobre a qual eles estão falando.

vartec
fonte
2

Se eu usar bloqueios, meu algoritmo ainda pode estar livre de bloqueios?

Poderia ser, mas depende do algoritmo.

Se eu tiver uma estrutura de dados simples, como uma fila, protegida por um bloqueio, um processo sempre poderá progredir, pois um processo pode adquirir o bloqueio, fazer o que ele deseja e liberá-lo.

Então, ele atende à definição de lock-free?

Nota per se .

Se a etapa "faça o que quiser" não envolver a aquisição de outros bloqueios e for garantida a conclusão em um tempo finito, essa parte específica do seu algoritmo estará livre de impasse.

No entanto, se essas pré-condições não forem atendidas, há pelo menos o potencial de conflitos ...

Stephen C
fonte
Após algum estudo do texto em The Art of Multiprocessor Programming, cheguei à conclusão de que os mutexes definitivamente invalidam a definição de lock-free, quando a definição está corretamente especificada. Adicionei uma resposta a esta página para esclarecer isso.
Marko Topolnik
1

O exemplo que você dá não é bloqueado pelo seguinte motivo.

O suporte a um encadeamento adquire o bloqueio e o agendador do SO suspendeu o encadeamento por um período infinito e solitário; então, todo o encadeamento não pode progredir, pois não é possível adquirir o bloqueio adquirido pelo encadeamento suspenso.

De um modo geral, algoritmos que usam bloqueios não são livres de bloqueios.

Observe que sem conflito e sem bloqueio são dois conceitos diferentes. sem impasse significa que não há possibilidade de impasse, mas poderia haver impasse que pode impedir que todo o sistema progrida. A liberdade de bloqueio é mais forte do que isso, porque significa que alguns encadeamentos no sistema sempre progridem com um número finito de etapas.

Chaoran
fonte
Observe uma definição mais cuidadosa na Wikipedia: "Um algoritmo é livre de bloqueios se satisfizer que, quando os threads do programa são executados suficientemente longos, pelo menos um dos threads progride." Isso exclui o caso de interrupção de encadeamentos. O progresso também é coberto pela liberdade de obstrução , não pela liberdade de bloqueio .
Marko Topolnik
@MarkoTopolnik Seu comentário não faz sentido. A liberdade de bloqueio cobre a liberdade de obstrução. Qualquer coisa que esteja livre de travas deve estar livre de obstruções. E a definição que você deu não exclui os threads de interrupção.
Chaoran
Por favor, tome cuidado para distinguir "fazer sentido" de "estar correto". Meu comentário está incorreto, como pode ser visto na minha resposta subsequente. Mas a definição da Wikipedia também está errada ou pelo menos ambígua.
Marko Topolnik
@MarkoTopolnik Como você admite que seu comentário não está correto, remova-o para evitar confundir outros leitores. A Wikipedia geralmente é incorreta ou ambígua. Você deve encontrar definições sutis como "liberdade de bloqueio" em trabalhos acadêmicos como cs.rochester.edu/~scott/papers/2006_PPoPP_synch_queues.pdf (a definição de livre de bloqueio está na seção 2.1)
Chaoran
Sim, incluir a propriedade nonblocking como parte da definição de liberdade de bloqueio é uma maneira de fazê-lo. Isso foi afirmado em uma revisão anterior da minha resposta.
Marko Topolnik