Por que todos os Objetos Java tem wait() e notify() e isso causa um impacto na performance?

StackOverflow https://stackoverflow.com/questions/1648551

  •  22-07-2019
  •  | 
  •  

Pergunta

Cada Java Object tem os métodos wait() e notify() (e variantes adicionais).Eu nunca usei esses e suspeito que muitos outros não.Por que eles são tão fundamental que cada objeto tem para tê-los e há uma queda de desempenho em tê-los (provavelmente algum estado é armazenado no-los)?

EDITAR para enfatizar a questão.Se eu tiver uma List<Double> com 100.000 elementos, em seguida, a cada Double tem esses métodos, como é estendida a partir de Object.Mas parece improvável que todos estes têm que saber sobre os segmentos que gerenciar o List.

EDITAR excelente e útil respostas.@Jon tem um blog muito bom post que cristalizaram a minha intuição.Eu também concordo completamente com @Bob_Cross que você deve mostrar um problema de desempenho antes de se preocupar com isso.(Também como o n-ésimo lei do bem-sucedida línguas se tivesse sido um impacto no desempenho, em seguida, Sol ou alguém teria fixa-lo).

Foi útil?

Solução

Bem, isso significa que todo objeto precisa potencialmente ter um monitor associado a ele. O mesmo monitor é usado para synchronized. Se você concorda com a decisão de ser capaz de sincronizar em qualquer objeto, então wait() e notify() Não adicione mais estado por objeto. A JVM pode alocar o monitor real preguiçosamente (eu sei .NET), mas deve haver algum espaço de armazenamento disponível para dizer qual monitor está associado ao objeto. É certo que é possível que essa seja uma quantidade muito pequena (por exemplo, 3 bytes), que na verdade não salvaria nenhuma memória devido ao preenchimento do restante da sobrecarga do objeto - você teria que ver como cada JVM individual lidou com a memória para dizer com certeza.

Observe que apenas ter extra métodos não afeta o desempenho (exceto um pouco devido ao fato de o código óbvio estar presente em algum lugar). Não é como se cada objeto ou mesmo cada tipo tenha sua própria cópia do código para wait() e notify(). Dependendo de como os vtables funcionam, cada tipo poderia Acabar com uma entrada VTable extra para cada método herdado - mas isso ainda é apenas por tipo, não por objeto. Isso basicamente vai se perder no barulho em comparação com a maior parte do armazenamento que é para os próprios objetos reais.

Pessoalmente, sinto que tanto .NET quanto Java cometeram um erro ao associar um monitor a todos os objetos - prefiro ter objetos explícitos de sincronização. Eu escrevi um pouco mais sobre isso em um Postagem no blog sobre redesenhar java.lang.object/System.object.

Outras dicas

Por que eles são tão fundamentais que cada objeto tem para tê-los e é há uma queda de desempenho em tê-los (provavelmente algum estado é armazenado em - os)?

tl;dr:Eles são thread-safety métodos e eles têm pequenas custos em relação ao seu valor.

As realidades fundamentais que estes métodos suporte são:

  1. Java é sempre multi-threaded.Exemplo:confira a lista de Threads utilizados por um processo usando o jconsole ou jvisualvm algum tempo.
  2. A precisão é mais importante do que o "desempenho". Quando eu estava projetos de classificação (há muitos anos), eu costumava ter que explicar "chegando a uma resposta errada muito rápido ainda está errado."

Fundamentalmente, esses métodos fornecem alguns ganchos para gerenciar por Objeto monitores utilizados na sincronização.Especificamente, se eu tenho synchronized(objectWithMonitor) em um método em particular, que eu possa usar objectWithMonitor.wait() para produzir esse monitor (por exemplo, se eu preciso de um outro método para concluir um cálculo antes de prosseguir).Nesse caso, o que vai permitir um outro método que foi bloqueado à espera que um monitor para prosseguir.

Por outro lado, eu posso usar objectWithMonitor.notifyAll() para deixar Threads que estão aguardando para o monitor de saber que eu vou estar abandonando o monitor em breve.Eles realmente não é possível continuar até eu deixar o bloco sincronizado, embora.

Com relação aos exemplos específicos (por exemplo, longas Listas de duplicatas), onde você pode preocupar-se que há um desempenho de memória ou bater no mecanismo de monitoramento, aqui estão alguns pontos que você deve provavelmente considerar:

  1. Primeiro, provar.Se você acha que há um grande impacto a partir de um núcleo Java mecanismo tais como multi-threaded exatidão, há uma excelente chance de que a sua intuição é falso.Medir o impacto do primeiro.Se a coisa é séria e você sei que você nunca vai precisar sincronizar em um indivíduo Duplo, considere o uso de duplas em vez disso.
  2. Se você não tem certeza de que você, seu colega de trabalho, um futuro de manutenção codificador (que pode ser você mesmo um ano depois), etc., nunca nunca nunca precisa de um bom granularidade de theaded acesso aos seus dados, há uma excelente chance de que, tendo esses monitores de distância só iria tornar o código menos flexível e de fácil manutenção.

Acompanhamento em resposta à pergunta sobre por Objeto vs.explícita de objetos do monitor:

Resposta curta: @JonSkeet:sim, removendo os monitores poderia criar problemas:ele iria criar atrito.Manter os monitores em Object lembra-nos que este é sempre um sistema multithread.

O objeto interno monitores não são sofisticados, mas eles são:fácil de explicar;trabalho de uma forma previsível;e são claros em seus objetivos. synchronized(this) é uma declaração de intenção.Se nós vigor iniciante codificadores para usar a simultaneidade pacote exclusivamente, apresentamos o atrito.O que está no pacote?O que é um semáforo?Fork-join?

Um programador iniciante pode usar o Objeto de monitores para escrever decente modelo-vista-controlador de código. synchronized, wait e notifyAll pode ser usado para implementar ingênua (no sentido de simples, acessível, mas talvez não o sangramento da borda de desempenho) de segurança do thread.O exemplo canônico seria uma dessas Duplas (apresentada pelo OP), o que pode ter um Segmento definido um valor, enquanto o AWT thread obtém o valor para colocá-lo em um JLabel.Nesse caso, não há nenhuma boa razão para criar explicitamente um Objeto adicional apenas para ter um monitor externo.

Em um ligeiramente maior nível de complexidade, esses mesmos métodos são úteis como um acompanhamento externo de método.No exemplo acima, eu explicitamente fiz isso (ver objectWithMonitor fragmentos acima).Novamente, esses métodos são muito úteis para montar relativamente simples da linha de segurança.

Se você gostaria de ser ainda mais sofisticado, eu acho que você deve pensar seriamente sobre a leitura Java Simultaneidade Na Prática (se você não tiver).Ler e escrever bloqueios são muito poderosos, sem adicionar muito mais complexidade.

Frase de efeito: Usando o basic métodos de sincronização, você pode explorar uma grande parte do desempenho habilitado por modernos processadores multi-core com rosca de segurança e sem um monte de sobrecarga.

Todos os objetos em Java têm monitores associados a eles. As primitivas de sincronização são úteis em praticamente todo o código multithread e seu semanticamente muito bom sincronizar o (s) objeto (s) que você está acessando, em vez de em objetos "monitor" separados.

O Java pode alocar os monitores associados aos objetos conforme necessário - como .NET - e, em qualquer caso, a sobrecarga real para simplesmente alocar (mas não usar) a trava seria muito pequena.

Em resumo: é realmente conveniente armazenar objetos com seus bits de suporte de segurança de threads, e há muito pouco impacto no desempenho.

Esses métodos estão por perto para implementar a comunicação entre thread.

Verificar Este artigo sobre o assunto.

Regras para esses métodos, retirados desse artigo:

  • Wait () informa o encadeamento de chamada para desistir do monitor e dormir até que algum outro thread entre no mesmo monitor e chamadas notificar ().
  • notify () acorda o primeiro thread que chamou wait () no mesmo objeto.
  • notifyAll () acorda todos os threads que chamavam wait () no mesmo objeto. O encadeamento de maior prioridade será executado primeiro.

Espero que isto ajude...

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