Como sincronizar uma variável estática entre segmentos executando diferentes instâncias de uma class em Java?

Eu sei que usando a palavra synchronize chave synchronize antes de um método traz a synchronization para esse object. Ou seja, 2 threads executando a mesma instância do object serão sincronizados.

No entanto, como a synchronization está no nível do object, dois encadeamentos que executam instâncias diferentes do object não serão sincronizados. Se tivermos uma variável estática em uma class Java que é chamada pelo método, gostaríamos que ela fosse sincronizada entre as instâncias da class. As duas instâncias estão sendo executadas em dois segmentos diferentes.

Podemos conseguir a synchronization da seguinte maneira?

 public class Test { private static int count = 0; private static final Object lock= new Object(); public synchronized void foo() { synchronized(lock) { count++; } } } 

É verdade que, como definimos um lock object que é estático e estamos usando a palavra synchronized chave synchronized para esse bloqueio, a count variables ​​estáticas agora está sincronizada entre as instâncias da class Test ?

Existem várias maneiras de sincronizar o access a uma variável estática.

  1. Use um método estático sincronizado. Isso sincroniza no object de class.

     public class Test { private static int count = 0; public static synchronized void incrementCount() { count++; } } 
  2. Sincronizar explicitamente no object de class.

     public class Test { private static int count = 0; public void incrementCount() { synchronized (Test.class) { count++; } } } 
  3. Sincronize em algum outro object estático.

     public class Test { private static int count = 0; private static final Object countLock = new Object(); public void incrementCount() { synchronized (countLock) { count++; } } } 

O método 3 é o melhor em muitos casos porque o object de bloqueio não é exposto fora de sua class.

Se você simplesmente estiver compartilhando um contador, considere usar um AtomicInteger ou outra class adequada do pacote java.util.concurrent.atomic:

 public class Test { private final static AtomicInteger count = new AtomicInteger(0); public void foo() { count.incrementAndGet(); } } 

Sim, é verdade.

Se você criar duas instâncias de sua class

 Test t1 = new Test(); Test t2 = new Test(); 

Então t1.foo e t2.foo ambos sincronizam no mesmo object estático e, portanto, bloqueiam um ao outro.

Você pode sincronizar seu código sobre a class. Isso seria mais simples.

  public class Test { private static int count = 0; private static final Object lock= new Object(); public synchronized void foo() { synchronized(Test.class) { count++; } } } 

Espero que você ache esta resposta útil.

Se é apenas sobre este inteiro, você também pode usar

Interlocked.Increment(count)

(namespace é System.Threading).