Bloco sincronizado de Java para .class


Respostas:


144

O snippet synchronized(X.class)usa a instância da classe como um monitor. Como há apenas uma instância de classe (o objeto que representa os metadados da classe em tempo de execução), um thread pode estar neste bloco.

Com synchronized(this)o bloqueio fica guardado pela instância. Para cada instância, apenas um thread pode entrar no bloco.

synchronized(X.class)é usado para garantir que haja exatamente um Thread no bloco. synchronized(this)garante que haja exatamente um encadeamento por instância. Se isso torna o código real no bloco seguro para thread, depende da implementação. Se mutate, apenas o estado da instância synchronized(this)é suficiente.


6
"tantos threads podem entrar no bloco quantas forem as instâncias" implica que a segunda forma atua como um semáforo, o que não é verdadeiro. Você deve dizer algo como: "synchronized (this) garante que apenas um thread pode entrar no bloco para uma determinada instância da classe".
liwp

Corrigido. Eu pretendia dizer isso.
Thomas Jung

2
qual é a instância da classe vs a instância?
Weishi Zeng

Portanto, se você tiver um método estático e não quiser sincronizar todo o seu corpo, sincronizar (isso) não é bom, em vez disso, sincronizar (Foo.class) é apropriado. Isso está certo?
krupal.agile

84

Para adicionar às outras respostas:

static void myMethod() {
  synchronized(MyClass.class) {
    //code
  }
}

é equivalente a

static synchronized void myMethod() {
  //code
}

e

void myMethod() {
  synchronized(this) {
    //code
  }
}

é equivalente a

synchronized void myMethod() {
  //code
}

12
Levei uma segunda leitura para perceber que os primeiros dois exemplos têm a palavra-chave "estático". Apenas apontando isso para outras pessoas que podem ter visto isso e não percebido. Sem a palavra-chave estática, os primeiros dois exemplos não seriam os mesmos.
kurtzbot

1
Esses exemplos NÃO são equivalentes! Os métodos sincronizados são "sincronizados" como um buraco quando um thread tenta chamar os métodos. Os blocos, por outro lado, podem ter código acima e abaixo deles, que podem ser executados a partir de vários threads. Eles só sincronizam dentro do bloco! Isso não é o mesmo!
JacksOnF1re

public static Singleton getInstance () {if (instância == null) {synchronized (Singleton.class) {instance = new Singleton (); }} instância de retorno; }
JacksOnF1re

2
A questão toda é que não é nenhum código fora dos synchronizedblocos. Isso os torna equivalentes. Se você mudar um exemplo, eles realmente não são mais os mesmos.
Jorn

22

Não, o primeiro obterá um bloqueio na definição de classe de MyClass, nem todas as instâncias dela. No entanto, se usado em uma instância, isso bloqueará efetivamente todas as outras instâncias, uma vez que compartilham uma única definição de classe.

O segundo obterá um bloqueio apenas na instância atual.

Se isso torna seu thread de objetos seguro, essa é uma questão muito mais complexa - precisaríamos ver seu código!


1
sim, MyClass.class pode ser qualquer variável estática e ter o mesmo efeito.
pstanton
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.