Tenho algumas perguntas sobre o uso e o significado da synchronized
palavra - chave.
- Qual é o significado da
synchronized
palavra - chave? - Quando devem ser os métodos
synchronized
? - O que significa programaticamente e logicamente?
java
multithreading
keyword
synchronized
Johanna
fonte
fonte
Respostas:
A
synchronized
palavra-chave se refere a diferentes segmentos de leitura e gravação nas mesmas variáveis, objetos e recursos. Este não é um tópico trivial em Java, mas aqui está uma citação da Sun:Em poucas palavras: quando você tem dois threads que estão lendo e gravando no mesmo 'recurso', digamos uma variável chamada
foo
, é necessário garantir que esses threads acessem a variável de maneira atômica. Sem asynchronized
palavra - chave, seu encadeamento 1 pode não ver o encadeamento de alteração 2 feito parafoo
, ou pior, pode ser apenas parcialmente alterado. Isso não seria o que você espera logicamente.Novamente, este é um tópico não trivial em Java. Para saber mais, explore os tópicos aqui no SO e nas Interwebs sobre:
Continue explorando esses tópicos até o nome "Brian Goetz" se tornar permanentemente associado ao termo "simultaneidade" em seu cérebro.
fonte
Bem, acho que tínhamos explicações teóricas suficientes, então considere este código
Nota:
synchronized
bloqueia a chamada do próximo segmento ao método test () desde que a execução do segmento anterior não esteja concluída. Os threads podem acessar esse método, um de cada vez. Semsynchronized
todos os threads, você pode acessar esse método simultaneamente.Quando um thread chama o método sincronizado 'test' do objeto (aqui o objeto é uma instância da classe 'TheDemo') ele adquire o bloqueio desse objeto, qualquer novo thread não pode chamar QUALQUER método sincronizado do mesmo objeto, desde que o thread anterior que adquiriu a trava não libera a trava.
O mesmo ocorre quando qualquer método estático sincronizado da classe é chamado. O encadeamento adquire o bloqueio associado à classe (nesse caso, qualquer método sincronizado não estático de uma instância dessa classe pode ser chamado por qualquer encadeamento porque esse bloqueio no nível do objeto ainda está disponível). Qualquer outro encadeamento não poderá chamar nenhum método estático sincronizado da classe, desde que o bloqueio no nível da classe não seja liberado pelo encadeamento que atualmente mantém o bloqueio.
Saída com sincronizado
Saída sem sincronizado
fonte
synchronized
, mas a consistência da memória é ignorada.A
synchronized
palavra-chave impede o acesso simultâneo a um bloco de código ou objeto por vários encadeamentos. Todos os métodos deHashtable
sãosynchronized
, portanto, apenas um encadeamento pode executar qualquer um deles por vez.Ao usar não-
synchronized
construções comoHashMap
, você deve criar recursos de segurança de thread em seu código para evitar erros de consistência.fonte
synchronized
significa que em um ambiente multiencadeado, um objeto comsynchronized
método (s) / bloco (s) não permite que dois threads acessem osynchronized
(s) método (s) / bloco (s) de código ao mesmo tempo. Isso significa que um thread não pode ler enquanto outro thread o atualiza.O segundo thread aguardará até que o primeiro thread conclua sua execução. A sobrecarga é a velocidade, mas a vantagem é a consistência garantida dos dados.
Se seu aplicativo for de thread único,
synchronized
blocos não oferecem benefícios.fonte
o
synchronized
palavra-chave faz com que um encadeamento obtenha um bloqueio ao inserir o método, para que apenas um encadeamento possa executar o método ao mesmo tempo (para a instância do objeto especificada, a menos que seja um método estático).Isso é chamado frequentemente de tornar a classe segura para threads, mas eu diria que isso é um eufemismo. Embora seja verdade que a sincronização protege o estado interno do vetor de ser corrompido, isso geralmente não ajuda muito o usuário do vetor.
Considere isto:
Embora os métodos envolvidos sejam sincronizados, porque estão sendo bloqueados e desbloqueados individualmente, infelizmente dois threads cronometrados podem criar um vetor com dois elementos.
Portanto, você também precisa sincronizar o código do aplicativo.
Como a sincronização no nível do método é a) cara quando você não precisa eb) insuficiente quando precisa da sincronização, agora existem substituições não sincronizadas (ArrayList no caso de Vector).
Mais recentemente, o pacote de simultaneidade foi lançado, com vários utilitários inteligentes que cuidam de problemas com vários threads.
fonte
Visão geral
A palavra-chave sincronizada em Java tem a ver com segurança de encadeamento, ou seja, quando vários encadeamentos lêem ou gravam a mesma variável.
Isso pode acontecer diretamente (acessando a mesma variável) ou indiretamente (usando uma classe que usa outra classe que acessa a mesma variável).
A palavra-chave sincronizada é usada para definir um bloco de código no qual vários threads podem acessar a mesma variável de maneira segura.
Mais profundo
Em termos de sintaxe, a
synchronized
palavra-chave recebe umObject
parâmetro como é (chamado de objeto de bloqueio ), que é seguido por a{ block of code }
.Quando a execução encontra essa palavra-chave, o encadeamento atual tenta "bloquear / adquirir / possuir" (faça a sua escolha) o objeto de bloqueio e execute o bloco de código associado após a aquisição do bloqueio.
Qualquer gravação em variáveis dentro do bloco de código sincronizado é garantida para ser visível para todos os outros encadeamentos que executam código de forma semelhante dentro de um bloco de código sincronizado usando o mesmo objeto de bloqueio .
Somente um encadeamento de cada vez pode reter o bloqueio, durante o qual todos os outros encadeamentos que tentam adquirir o mesmo objeto de bloqueio aguardam (pausam sua execução). O bloqueio será liberado quando a execução sair do bloco de código sincronizado.
Métodos sincronizados:
Adicionando
synchronized
palavra-chave para uma definição do método é igual a todo o corpo do método a ser enrolado num bloco de código sincronizado com o bloqueio objeto serthis
(para os métodos de instância) eClassInQuestion.getClass()
(para os métodos da classe) .- Método de instância é um método que não possui
static
palavra-chave.- Método de classe é um método que possui
static
palavra - chave.Técnico
Sem sincronização, não é garantido em que ordem as leituras e gravações acontecem, possivelmente deixando a variável com lixo.
(Por exemplo, uma variável pode acabar com metade dos bits gravados por um thread e metade dos bits gravados por outro thread, deixando a variável em um estado que nenhum dos threads tentou escrever, mas uma bagunça combinada de ambos.)
Não é suficiente concluir uma operação de gravação em um encadeamento antes (hora do relógio da parede) de outro encadeamento, porque o hardware poderia ter armazenado em cache o valor da variável e o encadeamento de leitura veria o valor em cache em vez do que foi gravado em isto.
Conclusão
Portanto, no caso de Java, você deve seguir o Java Memory Model para garantir que os erros de segmentação não ocorram.
Em outras palavras: use sincronização, operações atômicas ou classes que as utilizem sob o capô.
fonte
Pense nisso como uma espécie de catraca como você pode encontrar em um campo de futebol. Existem vapores paralelos de pessoas que querem entrar, mas na catraca são "sincronizados". Somente uma pessoa de cada vez pode passar. Todos aqueles que desejam passar o farão, mas podem ter que esperar até que possam passar.
fonte
Os encadeamentos se comunicam principalmente compartilhando o acesso aos campos e os campos de referência de objetos a que se referem. Essa forma de comunicação é extremamente eficiente, mas possibilita dois tipos de erros: interferência de encadeamento e erros de consistência de memória . A ferramenta necessária para evitar esses erros é a sincronização.
Os blocos ou métodos sincronizados evitam a interferência do encadeamento e asseguram que os dados sejam consistentes. A qualquer momento, apenas um encadeamento pode acessar um método ou bloco sincronizado ( seção crítica ) adquirindo um bloqueio. Outras threads aguardam a liberação do bloqueio para acessar a seção crítica .
Os métodos são sincronizados quando você adiciona
synchronized
à definição ou declaração do método. Você também pode sincronizar um bloco de código específico com um método.Isso significa que apenas um encadeamento pode acessar a seção crítica adquirindo um bloqueio. A menos que esse thread libere esse bloqueio, todos os outros threads precisarão esperar para adquirir um bloqueio. Eles não têm acesso para entrar na seção crítica sem adquirir a trava.
Isso não pode ser feito com uma mágica. É responsabilidade do programador identificar seções críticas no aplicativo e protegê-lo adequadamente. O Java fornece uma estrutura para proteger seu aplicativo, mas onde e o que todas as seções a serem protegidas são de responsabilidade do programador.
Mais detalhes na página de documentação do java
Bloqueios intrínsecos e sincronização:
Todo objeto tem um bloqueio intrínseco associado a ele . Por convenção, um encadeamento que precisa de acesso exclusivo e consistente aos campos de um objeto precisa adquirir o bloqueio intrínseco do objeto antes de acessá-los e liberar o bloqueio intrínseco quando terminar com eles.
Diz-se que uma linha possui a trava intrínseca entre o momento em que ela adquiriu a trava e a liberou. Desde que um encadeamento possua um bloqueio intrínseco, nenhum outro encadeamento poderá adquirir o mesmo bloqueio. O outro encadeamento será bloqueado quando tentar obter o bloqueio.
A sincronização de métodos tem dois efeitos :
Quando um encadeamento está executando um método sincronizado para um objeto, todos os outros encadeamentos que invocam métodos sincronizados para o mesmo bloco de objeto (suspender a execução) até que o primeiro encadeamento seja concluído com o objeto.
Isso garante que as alterações no estado do objeto sejam visíveis para todos os threads.
Procure outras alternativas para sincronização em:
Evitar sincronizado (isso) em Java?
fonte
Synchronized normal method
equivalente aSynchronized statement
(use isso)Synchronized static method
equivalente aSynchronized statement
(use class)Instrução sincronizada (usando variável)
Pois
synchronized
, temos ambosSynchronized Methods
eSynchronized Statements
. No entanto,Synchronized Methods
é semelhante aoSynchronized Statements
que precisamos entenderSynchronized Statements
.=> Basicamente, teremos
Aqui estão 2 que ajudam a entender
synchronized
intrinsic lock
associado a ele.synchronized statement
, adquire automaticamente ointrinsic lock
para essesynchronized statement's
objeto e libera-lo quando o método retorna. Enquanto um segmento possuir umintrinsic lock
, nenhum outro segmento poderá adquirir o SAME lock => thread safe.=> Quando um
thread A
invocasynchronized(this){// code 1}
=> todo o código de bloco (classe interna) onde havesynchronized(this)
e allsynchronized normal method
(classe interna) estão bloqueados porque o mesmo bloqueio. Ele será executado após othread A
desbloqueio ("// código 1" concluído).Esse comportamento é semelhante a
synchronized(a variable){// code 1}
ousynchronized(class)
.SAME LOCK => lock (não depende de qual método? Ou de quais instruções?)
Usar método sincronizado ou instruções sincronizadas?
Eu prefiro
synchronized statements
porque é mais extensível. Por exemplo, no futuro, você só precisa sincronizar uma parte do método. Por exemplo, você tem 2 métodos sincronizados e eles não são relevantes um para o outro; no entanto, quando um thread executa um método, ele bloqueia o outro método (pode ser impedido pelo usosynchronized(a variable)
).No entanto, aplicar o método sincronizado é simples e o código parece simples. Para algumas classes, existe apenas um método sincronizado, ou todos os métodos sincronizados na classe, relevantes entre si => podemos usar
synchronized method
para tornar o código mais curto e fácil de entenderNota
(isso não é relevante para muitos
synchronized
, é a diferença entre objeto e classe ou não estático e estático).synchronized
o método normal ousynchronized(this)
ousynchronized(non-static variable)
ele será sincronizado com base em cada instância do objeto.synchronized
um método estático ousynchronized(class)
ousynchronized(static variable)
ele será sincronizado com base na classeReferência
https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html https://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html
Espero que ajude
fonte
Aqui está uma explicação de The Java Tutorials .
Considere o seguinte código:
fonte
Para meu entendimento, sincronizado basicamente significa que o compilador escreve um monitor.enter e monitor.exit em torno do seu método. Como tal, pode ser seguro para threads, dependendo de como é usado (o que quero dizer é que você pode escrever um objeto com métodos sincronizados que não são seguros para threads, dependendo do que sua classe faz).
fonte
O que as outras respostas estão faltando é um aspecto importante: barreiras à memória . A sincronização de threads consiste basicamente em duas partes: serialização e visibilidade. Aconselho a todos que pesquisem no Google por "barreira da memória jvm", pois é um tópico não trivial e extremamente importante (se você modificar dados compartilhados acessados por vários threads). Feito isso, aconselho a olhar para as classes do pacote java.util.concurrent que ajudam a evitar o uso da sincronização explícita, o que, por sua vez, ajuda a manter os programas simples e eficientes, talvez até a impedir conflitos.
Um exemplo é ConcurrentLinkedDeque . Juntamente com o padrão de comando, ele permite criar encadeamentos de trabalho altamente eficientes, inserindo os comandos na fila simultânea - sem necessidade de sincronização explícita, sem bloqueios possíveis, sem interrupção explícita (), basta pesquisar a fila chamando take ().
Resumindo: a "sincronização de memória" ocorre implicitamente quando você inicia um thread, um thread termina, você lê uma variável volátil, desbloqueia um monitor (deixa um bloco / função sincronizada) etc. Essa "sincronização" afeta (em certo sentido) as descargas ") todas as gravações feitas antes dessa ação específica. No caso do ConcurrentLinkedDeque mencionado acima , a documentação "diz":
Esse comportamento implícito é um aspecto um tanto pernicioso, porque a maioria dos programadores Java sem muita experiência precisará de muito do que foi dado por causa disso. E, de repente, tropeça nesse encadeamento depois que o Java não está fazendo o que "deveria" fazer na produção, onde há uma carga de trabalho diferente - e é muito difícil testar problemas de simultaneidade.
fonte
Sincronizado significa simplesmente que vários encadeamentos, se associados a um único objeto, podem impedir a leitura e gravação sujas se o bloco sincronizado for usado em um objeto específico. Para dar mais clareza, vamos dar um exemplo:
Criamos dois objetos de classe MyRunnable, sendo runnable1 compartilhado com o thread 1 e thread 3 e runnable2 sendo compartilhados apenas com o thread 2. Agora, quando t1 e t3 são iniciados sem o uso sincronizado, a saída PFB sugere que os dois segmentos 1 e 3 afetam simultaneamente o valor var, onde no segmento 2, var possui sua própria memória.
Usando o Synchronzied, o thread 3 aguarda a conclusão do thread 1 em todos os cenários. Existem dois bloqueios adquiridos, um no runnable1 compartilhado pelo thread 1 e no thread 3 e outro no runnable2 compartilhado apenas pelo thread 2.
fonte
Sincronizado simples significa que não há dois segmentos que possam acessar o bloco / método simultaneamente. Quando dizemos que qualquer bloco / método de uma classe está sincronizado, significa que apenas um thread pode acessá-los por vez. Internamente, o encadeamento que tenta acessá-lo primeiro bloqueia esse objeto e, enquanto esse bloqueio não estiver disponível, nenhum outro encadeamento poderá acessar qualquer um dos métodos / blocos sincronizados dessa instância da classe.
Observe que outro encadeamento pode acessar um método do mesmo objeto que não está definido para ser sincronizado. Um encadeamento pode liberar o bloqueio chamando
fonte
synchronized
O bloco em Java é um monitor em multithreading.synchronized
bloco com o mesmo objeto / classe pode ser executado por apenas um thread, todos os outros estão aguardando. Pode ajudar narace condition
situação em que vários threads tentam atualizar a mesma variável (a primeira etapa é usarvolatile
About )Java 5
estendidosynchronized
apoiandohappens-before
[Sobre]O próximo passo é
java.util.concurrent
volátil vs sincronizado
fonte
sincronizada é uma palavra-chave em Java usada para fazer acontecer antes do relacionamento no ambiente de multithreading para evitar inconsistência de memória e erro de interferência de encadeamento.
fonte