Outras dicas

Esta questão merece uma resposta melhor.

ConcurrentLinkedQueue de Java é baseado no famoso algoritmo por Maged M. Michael e Michael L. Scott para sem bloqueio sem bloqueio filas .

"sem bloqueio" como um termo aqui para um recurso sustentou (nossa fila) significa que, independentemente do que programador da plataforma faz, como interromper um fio, ou se o fio em questão é simplesmente muito lento, outros segmentos disputando o mesmo recurso ainda será capaz de progredir. Se um bloqueio está envolvido, por exemplo, o thread que bloqueou poderia ser interrompido e todos os segmentos de espera para que o bloqueio seria bloqueado. fechaduras intrínsecas (a palavra-chave synchronized) em Java também pode vir com uma pena severa para o desempenho - como quando tendenciosa bloqueio está envolvido e você tem contenda, ou depois da VM decide 'inflar' o bloqueio após um período de rotação graça e bloco alegando tópicos ... é por isso que em muitos contextos (cenários de baixa / médio de contenção), fazendo comparar-e-conjuntos em referências atômicas pode ser muito mais eficiente e isso é exatamente o que muitos não-bloqueando dados-estruturas estão a fazer.

ConcurrentLinkedQueue de Java não é apenas para não-bloqueio, mas tem a propriedade impressionante que o produtor não lidar com o consumidor. Em um cenário único produtor / único consumidor (SPSC), isso realmente significa que não haverá disputa para falar. Em um cenário de consumo produtor / única múltipla, o consumidor não vai competir com os produtores. Essa fila tem disputa quando vários produtores tentam offer(), mas isso é a concorrência por definição. É basicamente um propósito geral e eficiente fila non-blocking.

Como para não ser um BlockingQueue, bem, bloqueando um fio que esperar em uma fila é uma maneira assustadoramente terrível de projetar sistemas concorrentes. não. Se você não consegue descobrir como usar um ConcurrentLinkedQueue em um cenário consumidor / produtor, em seguida, basta mudar para abstrações de nível superior, como um bom quadro ator.

blocos LinkedBlockingQueue o consumidor ou o produtor quando a fila está vazio ou cheio eo respectivo segmento consumidor / produtor é posto para dormir. Mas este recurso de bloqueio vem com um custo:. Cada venda ou levá operação é bloqueio sustentou entre os produtores ou consumidores (se muitos), portanto, em cenários com muitos produtores / consumidores a operação pode ser mais lenta

ConcurrentLinkedQueue não está usando bloqueios, mas CAS , por sua put / take operações potencialmente reduzindo a contenção com muitos segmentos produtores e consumidores. Mas sendo um "esperar free" estrutura de dados, ConcurrentLinkedQueue não vai bloquear quando vazio, o que significa que o consumidor terá de lidar com a take() retornando valores null por "espera ocupada", por exemplo, com o segmento do consumidor comendo CPU.

Então, qual é o "melhor" depende do número de segmentos de consumo, sobre a taxa que consomem / produção, etc. A referência é necessário para cada cenário.

Um caso de uso particular quando o ConcurrentLinkedQueue é claramente melhor é quando os produtores primeiro produzir algo e terminar seu trabalho, colocando o trabalho na fila de e só depois os consumidores começa a consumir, sabendo que eles vão ser feito quando fila está vazia. (Aqui há concorrência entre produtores e consumidores, mas apenas entre o produtor-produtor e consumidor-consumidor)

Outra solução (que não escala bem) é canais ENCONTRO: java.util.concurrent SynchronousQueue

Se a sua fila não é expansível e contém apenas um produtor / thread consumidor. Você pode usar lockless fila (Você não precisa para bloquear o acesso aos dados).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top