Respostas:
Como um método estático não possui um objeto associado, a palavra-chave sincronizada será bloqueada na classe, em vez do objeto?
Sim. :)
this
é o bloqueio adquirido nos métodos de instância -, por favor, corrija-o Oscar.
Apenas para adicionar um pequeno detalhe à resposta de Oscar (agradavelmente sucinta!), A seção relevante na Especificação da linguagem Java é 8.4.3.6, 'Métodos sincronizados' :
Um método sincronizado adquire um monitor ( §17.1 ) antes de executar. Para um método de classe (estático), o monitor associado ao objeto Class para a classe do método é usado. Para um método de instância, o monitor associado a este (o objeto para o qual o método foi chamado) é usado.
Um ponto sobre o qual você deve ter cuidado (vários programadores geralmente caem nessa armadilha) é que não há vínculo entre métodos estáticos sincronizados e métodos não estáticos sincronizados, ou seja:
class A {
static synchronized f() {...}
synchronized g() {...}
}
A Principal:
A a = new A();
Tópico 1:
A.f();
Tópico 2:
a.g();
f () eg () não são sincronizados entre si e, portanto, podem ser executados de forma totalmente simultânea.
synchronized (MyClass.class) {...}
,.
A menos que você implemente g () da seguinte maneira:
g() {
synchronized(getClass()) {
...
}
}
Acho esse padrão útil também quando quero implementar exclusão mútua entre diferentes instâncias do objeto (o que é necessário ao acessar um recurso externo, por exemplo).
getClass()
retorna o tipo de tempo de execução ; se você subclassificar a classe, a classe pai e a classe filho serão sincronizadas em bloqueios diferentes. synchronized(MyClass.class)
é o caminho a percorrer se você precisar garantir que todas as instâncias usem o mesmo bloqueio.
Dê uma olhada na página de documentação da Oracle em Bloqueios intrínsecos e sincronização
Você pode se perguntar o que acontece quando um método sincronizado estático é chamado, já que um método estático está associado a uma classe, não a um objeto. Nesse caso, o encadeamento adquire o bloqueio intrínseco para o objeto Class associado à classe . Portanto, o acesso aos campos estáticos da classe é controlado por um bloqueio distinto do bloqueio para qualquer instância da classe .
Um método estático também tem um objeto associado. Pertence ao arquivo Class.class no kit de ferramentas JDK. Quando o arquivo .class é carregado no ram, o Class.class cria uma instância chamada objeto de modelo.
Por exemplo: - quando você tenta criar um objeto da classe de cliente existente, como
Customer c = new Customer();
O Customer.class é carregado na RAM. Nesse momento, Class.class no JDK toolkit cria um objeto chamado Template objeto e carrega esse Customer.class nesse objeto de modelo. Os membros estáticos dessa Customer.class tornam-se atributos e métodos nesse objeto de modelo.
Portanto, um método ou atributo estático também tem um objeto
Os exemplos abaixo dão mais clareza entre bloqueio de classe e objeto; a esperança de que o exemplo abaixo também ajude outras pessoas :)
Por exemplo, temos os métodos abaixo: uma classe de aquisição e outra aquisição de bloqueio de objeto:
public class MultiThread {
public static synchronized void staticLock() throws InterruptedException {
for (int i = 0; i < 10; i++) {
Thread.sleep(100);
System.out.println(Thread.currentThread().getName() + " " + i);
}
}
public synchronized void objLock() throws InterruptedException {
for (int i = 0; i < 10; i++) {
Thread.sleep(100);
System.out.println(Thread.currentThread().getName() + " " + i);
}
}
}
Portanto, agora podemos ter os seguintes cenários:
Quando threads que usam o mesmo objeto tentam acessar o método objLock
OR ao staticLock
mesmo tempo (ou seja, ambos os threads estão tentando acessar o mesmo método)
Thread-0 0
Thread-0 1
Thread-0 2
Thread-0 3
Thread-0 4
Thread-1 0
Thread-1 1
Thread-1 2
Thread-1 3
Thread-1 4
Quando threads usando o mesmo objeto tentam acessar staticLock
e objLock
métodos ao mesmo tempo (tentam acessar métodos diferentes)
Thread-0 0
Thread-1 0
Thread-0 1
Thread-1 1
Thread-0 2
Thread-1 2
Thread-1 3
Thread-0 3
Thread-0 4
Thread-1 4
Quando threads usando Object diferente tentam acessar o staticLock
método
Thread-0 0
Thread-0 1
Thread-0 2
Thread-0 3
Thread-0 4
Thread-1 0
Thread-1 1
Thread-1 2
Thread-1 3
Thread-1 4
Quando threads usando Object diferente tentam acessar o objLock
método
Thread-0 0
Thread-1 0
Thread-0 1
Thread-1 1
Thread-0 2
Thread-1 2
Thread-1 3
Thread-0 3
Thread-0 4
Thread-1 4
Para aqueles que não são familiarizados com o método sincronizado estático bloqueado no objeto de classe, por exemplo, para a classe string, seu String.class enquanto o método sincronizado de instância bloqueia a instância atual de Object denotada pela palavra-chave "this" em Java. Como os dois objetos são diferentes, eles têm bloqueios diferentes. Enquanto um thread executa o método estático sincronizado, outro thread no java não precisa esperar o retorno do thread; ele adquirirá literalmente byte .class de bloqueio separado e entrará em método sincronizado estático.