Pergunta

Eu sou muito novo para Java e eu li que synchronized é "muito caro" em Java. Tudo o que eu quero saber é o que é caro e como é caro?

Graças.

Foi útil?

Solução

Talvez não seja tão ruim quanto você pensa

Ela costumava ser terrível (que é, possivelmente, por que você lê que era "muito caro"). Esses memes pode levar um longo tempo para morrer

Como caro é sincronização?

Por causa das regras envolvendo limpeza de cache e invalidação, um bloco sincronizado na linguagem Java é geralmente mais caro do que as instalações de seção crítica oferecidos por muitas plataformas, que são geralmente implementados com um "teste e conjunto de bits" atômica instrução de máquina. Mesmo quando um programa contém apenas um único segmento em execução em um único processador, uma chamada de método sincronizado ainda mais lento é do que uma chamada de método sincronizado-un. Se a sincronização requer realmente disputando o bloqueio, a penalidade de desempenho é substancialmente maior, uma vez que haverá vários interruptores fios e chamadas de sistema necessários.

Felizmente, melhorias contínuas na JVM ter tanto um melhor desempenho global do programa Java e reduziu o custo relativo de sincronização com cada lançamento, e melhorias futuras são antecipados. Além disso, os custos de sincronização de desempenho são muitas vezes exagerada. Uma fonte bem conhecida citou que uma chamada de método é sincronizada tanto quanto 50 vezes mais lenta do que uma chamada de método sincronizado-un. Embora esta afirmação pode ser verdadeira, é também bastante enganosa e levou muitos desenvolvedores evitar a sincronização mesmo em casos onde é necessário.

Tendo dito isto - programação concorrente ainda pode ser lento, mas não tanto do que é puramente culpa do Java agora. Há um trade-off entre o bem eo bloqueio grosso. Muito grossa é obviamente ruim, mas é possível ser muito bem também, como fechaduras têm um custo não zero.

É importante considerar o recurso específico sob contenção. discos rígidos mecânicos são um exemplo, onde mais threads pode levar a pior performance.

Outras dicas

É caro, porque se você estiver usando threads, e uma série de tópicos tem que passar por uma seção sincronizado de código, apenas um deles pode ser executado ao mesmo tempo.

É como um gargalo.

É ainda caro quando você usa um único segmento, porque tem de verificar qualquer maneira, se ele está autorizado a executar.

Se você reduzir o uso de segmentos sincronizados seu segmento não terá que parar para ver se eles podem executar (claro, eles não têm para compartilhar dados)

Uma visão geral de alto nível de como funciona a sincronização pode ser encontrada aqui

http://img20.imageshack.us/img20/2066/monitor28synchronizatioc.png

monitor de estilo Um Java

Este não é tão específico para Java. A sincronização pode ser considerado "caro" em qualquer ambiente multi-threaded se não for feito corretamente. Se é particularmente ruim em Java, eu não sei.

Ela impede que threads executados simultaneamente se eles usam o mesmo recurso. Mas, uma vez que do usar o mesmo recurso, não há melhor opção (que tem de ser feito).

O problema é que muitas vezes as pessoas proteger um recurso com o escopo de uma muito grande. Por exemplo, um programa mal concebidos podem sincronizar uma matriz inteira de objectos, em vez de cada elemento individual na matriz (ou mesmo uma secção da matriz).

Isto significaria que um fio tentando ler elemento 7 deve aguardar uma leitura fio ou elemento 22. Não é preciso escrever. Se a granularidade da sincronização estavam ao nível dos elementos em vez do nível de matriz, estes dois segmentos não possam interferir um com o outro.

Somente quando dois threads tentou acessar o mesma elemento haveria contenção de recursos. É por isso que a regra geral é proteger apenas como recurso um pequeno quanto possível (sujeito a limitações no número de sincronizações, é claro).

Mas, para ser honesto, não importa como é caro se a alternativa é a corrupção de dados devido a dois tópicos brigando por um único recurso. Escreva seu aplicativo corretamente e só se preocupar com problemas de desempenho, se e quando eles aparecem ( "começar a trabalhar primeiro então começar a trabalhar rápido" é um mantra das minhas favoritas).

Este artigo sobre a IBM realmente resume muito bem os pontos principais atrás de sincronização.

Por causa das regras envolvendo limpeza de cache e invalidação, um bloco sincronizado na linguagem Java é geralmente mais caro do que as instalações de seção crítica oferecidos por muitas plataformas, que são geralmente implementados com um "teste e conjunto de bits" atômica instrução de máquina. Mesmo quando um programa contém apenas um único segmento em execução em um único processador, uma chamada de método sincronizado ainda mais lento é do que uma chamada de método não sincronizada. Se a sincronização requer realmente disputando o bloqueio, a penalidade de desempenho é substancialmente maior, uma vez que haverá vários interruptores fios e chamadas de sistema necessários.

As outras respostas dar um bom nível de detalhe técnico que eu não estou indo para tentar replicar.

O que vou fazer é aconselhá-lo a verificar as datas dos artigos (bem como a competência implícita e percepção do autor). Sincronização em Java foi muito lento em JVMs anteriores. No entanto, ele melhorou muito recentemente, de modo que a sincronização uncontended é muito mais rápido do que você imagina, e sincronização uncontended melhorou também.

Lembre-se, esta pergunta, possivelmente, não importa - se você precisa sincronizar para assegurar a correção, você necessidade para sincronizar para assegurar exatidão. As únicas vezes que eu posso ver a velocidade sendo um problema é se você estava pensando em criar uma implementação lockless vez (usando o muito eficiente mas complexo java.util.concurrent.locks.AbstractQueuedSynchronizer ), ou talvez pensando em usar uma outra língua para a sua tarefa em seu lugar.

Em geral, eu acho que a melhor conclusão é que a sincronização é geralmente rápido o suficiente para usar em uma primeira iteração. Tal como acontece com todas as questões de desempenho, código de clareza e exatidão no primeiro e só então otimizar o que você mede a ser uma parte caro do seu aplicativo. Normalmente, este não será o custo de sincronização *.

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