Se eu sincronizei dois métodos na mesma classe, eles podem ser executados simultaneamente no mesmo objeto ? por exemplo:
class A {
public synchronized void methodA() {
//method A
}
public synchronized void methodB() {
// method B
}
}
Eu sei que não posso executar methodA()
duas vezes no mesmo objeto em dois segmentos diferentes. mesma coisa methodB()
.
Mas posso executar methodB()
em threads diferentes enquanto methodA()
ainda estiver em execução? (mesmo objeto)
obj.methodB()
é sinônimo deA.methodB()
quandomethodB()
éstatic
. Portanto, sim, eles irão bloquear (no monitor da classe, não no objeto)..class
objeto. Então, se você tiverclass A {static synchronized void m() {} }
. E então um thread chamanew A().m()
que adquire bloqueio nonew A()
objeto. Se, em seguida, outro segmento chamaA.m()
-lo ENTRA NO MÉTODO NO PROBLEMA porque o que ele procura é fechamento emA.class
objeto enquanto há segmentos possuem esse tipo de bloqueio . Portanto, mesmo que você tenha declarado o método,synchronized
ele é acessado por dois threads diferentes AO MESMO TEMPO . Assim: nunca use referências de objeto para chamar métodos estáticosNo exemplo methodA e methodB são métodos de instância (em oposição a métodos estáticos). Colocar
synchronized
um método de instância significa que o encadeamento precisa adquirir o bloqueio (o "bloqueio intrínseco") na instância do objeto em que o método é chamado antes que o encadeamento possa começar a executar qualquer código nesse método.Se você tiver dois métodos de instância diferentes marcados como sincronizados e segmentos diferentes estiverem chamando esses métodos simultaneamente no mesmo objeto, esses segmentos estarão disputando o mesmo bloqueio. Depois que um thread obtém o bloqueio, todos os outros threads são excluídos de todos os métodos de instância sincronizados nesse objeto.
Para que os dois métodos sejam executados simultaneamente, eles precisam usar bloqueios diferentes, como este:
onde a sintaxe do bloco sincronizado permite especificar um objeto específico no qual o encadeamento em execução precisa adquirir o bloqueio intrínseco para entrar no bloco.
O importante é entender que, apesar de colocarmos uma palavra-chave "sincronizada" em métodos individuais, o conceito principal é o bloqueio intrínseco nos bastidores.
Aqui está como o tutorial Java descreve o relacionamento:
O objetivo do bloqueio é proteger dados compartilhados. Você usaria bloqueios separados, como mostrado no código de exemplo acima, apenas se cada bloqueio protegesse diferentes membros de dados.
fonte
static synchronized
ousynchronized (A.class)
O Java Thread adquire um bloqueio no nível do objeto quando entra em um método java sincronizado da instância e adquire um bloqueio no nível da classe quando entra no método java sincronizado estático .
No seu caso, os métodos (instância) são da mesma classe. Portanto, sempre que um thread entra no método ou bloco sincronizado com java, ele adquire um bloqueio (o objeto no qual o método é chamado). Portanto, outro método não pode ser chamado ao mesmo tempo no mesmo objeto até que o primeiro método seja concluído e o bloqueio (no objeto) seja liberado.
fonte
private final Object lock = new object();
sincronizado para permitir que apenas um thread possa executar um dos métodos? ObrigadoNo seu caso, você sincronizou dois métodos na mesma instância da classe. Portanto, esses dois métodos não podem ser executados simultaneamente em diferentes segmentos da mesma instância da classe A. Mas eles podem em diferentes instâncias da classe A.
é o mesmo que:
fonte
private final Object lock = new Object();
e agora usarlock
com bloco sincronizado em dois métodos, sua declaração será verdadeira? IMO, pois Object é a classe pai de todos os objetos, portanto, mesmo se os threads estiverem em uma instância diferente da classe, apenas um poderá acessar o código dentro do bloco sincronizado por vez. Obrigado.No link da documentação da oracle
A sincronização de métodos tem dois efeitos:
Isso responderá à sua pergunta: No mesmo objeto, você não pode chamar o segundo método sincronizado quando a execução do primeiro método sincronizado estiver em andamento.
Consulte esta página de documentação para entender os bloqueios intrínsecos e o comportamento dos bloqueios.
fonte
Pense no seu código como o código abaixo:
Portanto, sincronizado no nível do método significa simplesmente sincronizado (isso). se algum encadeamento executar um método dessa classe, obteria o bloqueio antes de iniciar a execução e o manteria até a execução do método ser concluída.
Na verdade, não é possível!
Portanto, vários encadeamentos não poderão executar nenhum número de métodos sincronizados no mesmo objeto simultaneamente.
fonte
Com toda a clareza, é possível que o método sincronizado estático e não estático possa ser executado simultaneamente ou simultaneamente, porque um está com bloqueio no nível do objeto e outro bloqueio no nível da classe.
fonte
A idéia principal da sincronização, que não afunda facilmente, é que ela só terá efeito se os métodos forem chamados na mesma instância de objeto - ela já foi destacada nas respostas e comentários -
Abaixo, o programa de amostra deve identificar claramente o mesmo -
Observe a diferença na saída de como o acesso simultâneo é permitido conforme o esperado, se os métodos forem chamados em diferentes instâncias de objetos.
Ouput com noEffectOfSynchronizedAsMethodsCalledOnDifferentObjects () comentou - a saída está na ordem methodA in> methodA Out .. methodB in> methodB Out
e Ouput com synchronizedEffectiveAsMethodsCalledOnSameObject () comentado - a saída mostra o acesso simultâneo do método A pelo Thread1 e Thread0 na seção destacada -
Aumentar o número de threads tornará ainda mais visível.
fonte
Não, não é possível, se fosse possível, ambos os métodos poderiam estar atualizando a mesma variável simultaneamente, o que poderia facilmente corromper os dados.
fonte
Sim, eles podem executar simultaneamente os dois threads. Se você criar 2 objetos da classe, cada objeto conterá apenas um bloqueio e todo método sincronizado precisará de bloqueio. Portanto, se você deseja executar simultaneamente, crie dois objetos e tente executar usando a referência desses objetos.
fonte
Você está sincronizando no objeto que não está na classe. Então eles não podem rodar simultaneamente no mesmo objeto
fonte
Dois Threads diferentes que executam um método sincronizado comum no único objeto, já que o objeto é o mesmo, quando um thread o usa com o método sincronizado, ele deve varificar o bloqueio; se o bloqueio estiver ativado, esse segmento passará para o estado de espera, se o bloqueio estiver desativado, ele poderá acessar o objeto, enquanto o habilitará e trará o bloqueio somente quando a execução estiver concluída. quando os outros encadeamentos chegarem, ele modificará o bloqueio, uma vez que está ativado, esperará até que o primeiro encadeamento seja executado e libere o bloqueio colocado no objeto. Uma vez liberado o bloqueio, o segundo encadeamento terá acesso ao objeto e habilitará o bloqueio até sua execução. para que a execução não seja simultânea, os dois threads serão executados um a um,
fonte