Métodos estáticos sincronizados com Java: bloqueio no object ou class

Os Tutoriais Java dizem: “não é possível que duas invocações de methods sincronizados no mesmo object sejam intercaladas.”

O que isso significa para um static method ? Como um método estático não tem object associado, a palavra-chave sincronizada bloqueará a class, em vez do object?

Como um método estático não tem object associado, a palavra-chave sincronizada bloqueará a class, em vez do object?

Sim. 🙂

Apenas para adicionar um pequeno detalhe à resposta de Oscar (agradavelmente sucinta!), A seção relevante sobre a especificação da linguagem Java é 8.4.3.6, ‘Métodos sincronizados’ :

Um método sincronizado adquire um monitor (§17.1) antes de ser executado. Para um método de class (estático), o monitor associado ao object Class da class do método é usado. Para um método de instância, o monitor associado a ele (o object 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á nenhum link entre methods estáticos sincronizados e methods não estáticos sincronizados, isto é:

 class A { static synchronized f() {...} synchronized g() {...} } 

A Principal:

 A a = new A(); 

Tópico 1:

 Af(); 

Tópico 2:

 ag(); 

f () e g () não são sincronizados entre si e, portanto, podem ser executados de maneira totalmente simultânea.

A menos que você implemente g () da seguinte maneira:

 g() { synchronized(getClass()) { ... } } 

Eu acho este padrão útil também quando eu quero implementar a exclusão mútua entre diferentes instâncias do object (que é necessário quando se acessa um recurso externo, por exemplo).

Dê uma olhada na página de documentação da Oracle sobre Fechaduras Intrínsecas e Sincronização

Você pode se perguntar o que acontece quando um método estático sincronizado é invocado, já que um método estático é associado a uma class, não a um object. Nesse caso, o thread adquire o bloqueio intrínseco para o object de class associado à class . Assim, o access aos campos estáticos da class é controlado por um bloqueio que é diferente do bloqueio de qualquer instância da class .

Abaixo exemplos dá mais clareza entre class e bloqueio de object, a esperança abaixo exemplo ajudará os outros também 🙂

Por exemplo, temos abaixo os methods uma class de aquisição e outro bloqueio de object de aquisição:

 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); } } } 

Então, agora podemos ter os seguintes cenários:

  1. Quando os encadeamentos que usam o mesmo object tentam acessar o método staticLock OR staticLock mesmo tempo (ou seja, ambos os encadeamentos tentam 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 
  2. Quando os encadeamentos que usam o mesmo object tentam acessar os methods objLock e objLock mesmo tempo (tenta acessar methods 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 
  3. Quando encadeamentos usando objects diferentes tentam acessar o método staticLock

     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 
  4. Quando encadeamentos usando objects diferentes tentam acessar o método objLock

     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 

Um método estático também possui um object 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 dele chamada template object.

Por exemplo: – quando você tenta criar um object de class de cliente existente como

 Customer c = new Customer(); 

A carga Customer.class na RAM. Nesse momento, o Class.class no kit de ferramentas do JDK cria um Objeto chamado de object Modelo e carrega esse Customer.class nesse object de modelo. Os membros estatísticos desse Customer.class se tornam atributos e methods nesse object de modelo.

Então, um método ou atributo estático também tem um object

Para aqueles que não estão familiarizados com o método sincronizado estático bloqueado no object de class, por exemplo, para a class string seu String.class, enquanto o método de instância sincronizada bloqueia a instância atual do Object denotada pela palavra-chave “this” em Java. Como ambos os objects são diferentes, eles têm um bloqueio diferente, enquanto um thread está executando o método sincronizado estático, outro thread em java não precisa esperar que o thread retorne, em vez disso, ele irá adquirir um byte separado. método sincronizado estático.