Eu estava lendo a API java.util.concurrent e descobri que
CountDownLatch
: Um auxiliar de sincronização que permite que um ou mais threads esperem até que um conjunto de operações que estão sendo executadas em outros threads seja concluído.CyclicBarrier
: Um auxiliar de sincronização que permite que um conjunto de threads espere um pelo outro atingir um ponto de barreira comum.
Para mim, ambos parecem iguais, mas tenho certeza de que há muito mais.
Por exemplo, em CoundownLatch, the countdown value could not be reset, that can happen in the case of CyclicBarrier
.
Existe alguma outra diferença entre os dois? Onde
estão as pessoas use cases
que desejam redefinir o valor da contagem regressiva?
java
concurrency
countdownlatch
cyclicbarrier
sonhador
fonte
fonte
Respostas:
Uma grande diferença é que o CyclicBarrier executa uma tarefa executável (opcional) que é executada quando a condição de barreira comum é atendida.
Ele também permite que você obtenha o número de clientes aguardando na barreira e o número necessário para acionar a barreira. Uma vez acionada, a barreira é redefinida e pode ser usada novamente.
Para casos de uso simples - serviços iniciando etc ... um CountdownLatch é bom. Um CyclicBarrier é útil para tarefas de coordenação mais complexas. Um exemplo disso seria a computação paralela - onde várias subtarefas estão envolvidas na computação - como o MapReduce .
fonte
Há outra diferença.
Ao usar a
CyclicBarrier
, pressupõe-se que você especifique o número de threads em espera que acionam a barreira. Se você especificar 5, deverá ter pelo menos 5 threads para chamarawait()
.Ao usar a
CountDownLatch
, você especifica o número de chamadascountDown()
que resultarão na liberação de todos os threads em espera. Isso significa que você pode usar umCountDownLatch
com apenas um único thread."Por que você faria isso?", Você pode dizer. Imagine que você está usando uma API misteriosa codificada por outra pessoa que realiza retornos de chamada. Você deseja que um de seus threads aguarde até que um determinado retorno de chamada seja chamado várias vezes. Você não tem idéia em quais threads o retorno de chamada será chamado. Nesse caso, a
CountDownLatch
é perfeito, enquanto eu não consigo pensar em nenhuma maneira de implementar isso usando aCyclicBarrier
(na verdade, eu posso, mas envolve tempos limite ... eca!).Eu só desejo que
CountDownLatch
poderia ser reposto!fonte
CountDownLatch
redefinir - uma solução alternativa usada para implementar uma notificação de espera aproximada é apenas atualizarCountDownLatch
imediatamente quando o bloco de código protegido for inserido (quando a trava chegar a zero). Isso não é aplicável em todas as circunstâncias / escopos, é claro, mas achei interessante notar que é uma opção em situações de ouro.Java Concurrency in Practice
- diz a mesma coisa:Latches are for waiting for events; barriers are for waiting for other threads.
. Um ponto primário e essencial para entender a diferença entre esses dois.Um ponto que ninguém mencionou ainda é que, em a
CyclicBarrier
, se um encadeamento tiver um problema (tempo limite, interrompido ...), todos os outros que alcançaramawait()
obtêm uma exceção. Veja Javadoc:fonte
Eu acho que o JavaDoc explicou explicitamente as diferenças. A maioria das pessoas sabe que CountDownLatch não pode ser redefinido, no entanto, CyclicBarrier pode. Mas essa não é a única diferença, ou o CyclicBarrier pode ser renomeado para ResetbleCountDownLatch. Devemos dizer as diferenças da perspectiva de seus objetivos, descritos em JavaDoc.
CountDownLatch: um auxiliar de sincronização que permite que um ou mais encadeamentos esperem até que um conjunto de operações sendo executadas em outros encadeamentos seja concluído.
CyclicBarrier: um auxiliar de sincronização que permite que um conjunto de encadeamentos espere um pelo outro atingir um ponto de barreira comum.
Em countDownLatch, há um ou mais encadeamentos que aguardam um conjunto de outros encadeamentos a conclusão de . Nessa situação, existem dois tipos de encadeamentos, um tipo está aguardando, outro está fazendo alguma coisa, após concluir suas tarefas, eles podem estar aguardando ou apenas serem finalizados.
No CyclicBarrier, há apenas um tipo de encadeamentos, eles estão esperando um pelo outro, são iguais.
fonte
A principal diferença está documentada nos Javadocs para CountdownLatch. Nomeadamente:
source 1.6 Javadoc
fonte
Um CountDownLatch é usado para sincronização única. Ao usar um CountDownLatch, qualquer thread pode chamar countDown () quantas vezes quiser. Os encadeamentos que chamaram waitit () são bloqueados até que a contagem chegue a zero devido a chamadas para countDown () por outros encadeamentos desbloqueados. O javadoc para CountDownLatch afirma:
Por outro lado, a barreira cíclica é usada para vários pontos de sincronização, por exemplo, se um conjunto de threads estiver executando um cálculo em loop / em fases e precisar sincronizar antes de iniciar a próxima iteração / fase. Conforme o javadoc para CyclicBarrier :
Diferentemente do CountDownLatch, cada chamada para waitit () pertence a alguma fase e pode causar o bloqueio do encadeamento até que todas as partes pertencentes a essa fase invoquem waitit (). Não há operação countDown () explícita suportada pelo CyclicBarrier.
fonte
Esta pergunta já foi respondida adequadamente, mas acho que posso agregar um pouco adicionando algum código.
Para ilustrar o comportamento da barreira cíclica, fiz alguns exemplos de código. Assim que a barreira é inclinada, ela é redefinida automaticamente para que possa ser usada novamente (portanto, é "cíclica"). Quando você executa o programa, observe que as impressões "Vamos jogar" são acionadas somente depois que a barreira é derrubada.
fonte
Quando eu estava estudando sobre Latches e barreiras cíclicas, descobri essas metáforas. cyclicbarriers : imagine que uma empresa tenha uma sala de reuniões. Para iniciar a reunião, um certo número de participantes da reunião precisa comparecer à reunião (para oficializá-la). a seguir está o código de um participante da reunião normal (um funcionário)
funcionário ingressa na reunião, aguarda que outros venham para iniciar a reunião. ele também sai se a reunião for cancelada :) então temos o CHEFE como doses não gostam de esperar que outros apareçam e se ele perde o paciente, ele cancela a reunião.
Em um dia normal, os funcionários vêm à reunião esperar que outros apareçam e, se alguns participantes não vêm, têm que esperar indefinidamente! em alguma reunião especial, o chefe chega e ele não gosta de esperar (5 pessoas precisam começar a se reunir, mas apenas o chefe vem e também um funcionário entusiasmado); portanto, ele cancela a reunião (com raiva)
Resultado:
Há outro cenário em que outro segmento externo (um terremoto) cancela a reunião (método de redefinição de chamada). nesse caso, todos os threads em espera são ativados por uma exceção.
código em execução resultará em uma saída engraçada:
Você também pode adicionar uma secretária à sala de reunião. Se uma reunião for realizada, ela documentará tudo, mas não fará parte da reunião:
Travas : se o chefe zangado deseja realizar uma exposição para os clientes da empresa, tudo precisa estar pronto (recursos). fornecemos uma lista de tarefas a cada trabalhador (Thread) que administra seu trabalho e verificamos a lista de tarefas (alguns trabalhadores pintam, outros preparam sistema de som ...). quando todos os itens da lista de tarefas estiverem concluídos (os recursos são fornecidos), podemos abrir as portas para os clientes.
E os trabalhadores como estão preparando a exposição:
fonte
Em poucas palavras , apenas para entender as principais diferenças funcionais entre os dois:
e
exceto, é claro, recursos como bloqueio, espera temporizada, diagnóstico e tudo o que foi detalhado em detalhes nas respostas acima.
As classes acima são, no entanto, totalmente funcionais e equivalentes, dentro da funcionalidade fornecida, aos seus nomes correspondentes.
Em uma nota diferente,
CountDownLatch
as subclasses da classe internaAQS
, enquantoCyclicBarrier
usaReentrantLock
(minha suspeita é que poderia ser o contrário ou ambos poderiam usar o AQS ou ambos usar o Lock - sem perda de eficiência de desempenho)fonte
Uma diferença óbvia é que apenas N threads podem aguardar em um CyclicBarrier de N para serem liberados em um ciclo. Mas um número ilimitado de threads pode aguardar em um CountDownLatch de N. O decremento de contagem regressiva pode ser feito por um thread N vezes ou N threads uma vez cada ou combinações.
fonte
No caso de CyclicBarrier, assim que TODOS os threads filho começam a chamar de barreira.await (), o Runnable é executado na Barreira. A barreira.await em cada encadeamento filho levará um tempo diferente para concluir, e todos serão concluídos ao mesmo tempo.
fonte
No CountDownLatch , os threads principais aguardam que outros threads concluam sua execução. No CyclicBarrier , os encadeamentos de trabalho esperam um pelo outro para concluir sua execução.
Não é possível reutilizar a mesma instância CountDownLatch quando a contagem chegar a zero e a trava estiver aberta; por outro lado, o CyclicBarrier poderá ser reutilizado redefinindo a barreira, uma vez que a barreira seja quebrada.
fonte
CountDownLatch é uma contagem regressiva de qualquer coisa; CyclicBarrier é uma contagem regressiva apenas para encadeamento
suponha que existam 5 threads de trabalho e um thread de remetente e quando os trabalhadores produzem 100 itens, o remetente os envia.
Para CountDownLatch, o contador pode estar em trabalhadores ou itens
Para CyclicBarrier, o contador pode apenas em trabalhadores
Se um trabalhador adormecer infinitamente, com CountDownLatch nos itens, o Shipper poderá enviar; No entanto, com CyclicBarrier, o remetente nunca pode ser chamado
fonte
@ Kevin Lee e @ Jon Tentei o CyclicBarrier com o opcional Runnable. Parece que ele roda no começo e depois que o CyclicBarrier é derrubado. Aqui está o código e a saída
barreira estática CyclicBarrier;
Resultado
fonte