Comment synchroniser une variable statique parmi les threads exécutant différentes instances d'une classe en Java?

je sais que l'utilisation du mot-clé synchronize avant une méthode apporte la synchronisation à cet objet. C'est, 2 threads s'exécutant sur la même instance de l'objet seront synchronisés.

cependant, puisque la synchronisation se fait au niveau de l'objet, 2 threads exécutant différentes instances de l'objet ne seront pas synchronisés. Si nous avons une variable statique dans une classe Java qui est appelée par la méthode, nous aimerions qu'elle soit synchronisée à travers les instances de la classe. Les deux instances fonctionnent en 2 threads différents.

pouvons-nous réaliser la synchronisation de la manière suivante?

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

est-il vrai que puisque nous avons défini un objet lock qui est statique et que nous utilisons le mot-clé synchronized pour cette serrure, la variable statique count est maintenant synchronisée à travers les instances de la classe Test ?

107
demandé sur Shepmaster 2010-01-22 23:25:10

4 réponses

Il y a plusieurs façons de synchroniser l'accès à une variable statique.

  1. utilisez une méthode statique synchronisée. Cela synchronise sur l'objet class.

    public class Test {
        private static int count = 0;
    
        public static synchronized void incrementCount() {
            count++;
        }
    } 
    
  2. synchroniser explicitement sur l'objet de classe.

    public class Test {
        private static int count = 0;
    
        public void incrementCount() {
            synchronized (Test.class) {
                count++;
            }
        }
    } 
    
  3. Synchroniser sur un autre objet statique.

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

La méthode 3 est la meilleure dans de nombreux cas parce que l'objet lock n'est pas exposé en dehors de votre classe.

178
répondu Darron 2012-05-18 19:44:59

si vous partagez simplement un compteur, envisagez d'utiliser un AtomicInteger ou une autre classe appropriée du java.util.simultané.atomique du package:

public class Test {

    private final static AtomicInteger count = new AtomicInteger(0); 

    public void foo() {  
        count.incrementAndGet();
    }  
}
59
répondu Kevin 2010-01-22 20:46:20

Oui, c'est vrai.

si vous créez deux instances de votre classe

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

puis t1.foo et t2.les deux foo synchronisent sur le même objet statique et donc se bloquent l'un l'autre.

3
répondu richs 2010-01-22 20:44:54

Vous pouvez synchroniser votre code sur la classe. Ce serait plus simple.

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

j'Espère que vous trouverez cette réponse utile.

-1
répondu Jafar Ali 2013-01-12 09:18:55