131 votes

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

Je sais que l'utilisation de la synchroniser mot-clé avant une méthode apporte la synchronisation de l'objet.
C'est, 2 threads s'exécutant sur la même instance de l'objet seront synchronisés.
Cependant, depuis la synchronisation est au niveau de l'objet, 2 threads s'exécutant différentes instances de l'objet ne seront pas synchronisées. Donc, si nous avons une variable statique dans une classe java qui est appelée par la méthode, que l'on voudrait être synchronisés sur l'ensemble des instances de la classe.
Les deux instances sont en cours d'exécution dans les 2 threads différents.
Pouvons-nous obtenir une synchronisation de la manière suivante?

public class Test 
{ 
 private static int count = 0; 
 private static final de l'Objet de verrouillage= new Object(); 
 public synchronized void foo() 
 { 
synchronisée(lock)
 { 
 count++; 
 } 
 } 
}

Est-il vrai que, depuis, nous avons défini un objet de verrouillage qui est statique et nous utilisons le mot-clé synchronized pour que le verrouillage, l'statique varibale comte est maintenant synchronisés sur l'ensemble des instances de la classe de Test?

210voto

Darron Points 13196

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

  1. Utilisez une méthode statique synchronisée. Cela se synchronise sur l'objet de classe.

     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, car l'objet de verrouillage n'est pas exposé en dehors de votre classe.

65voto

Kevin Points 19613

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

 public class Test {

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

    public void foo() {  
        count.incrementAndGet();
    }  
}
 

4voto

richs Points 1710

Oui c'est vrai.

Si vous créez deux instances de votre classe

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

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

0voto

Jafar Ali Points 86

Vous pouvez synchroniser votre code sur la classe. Ce serait le 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.

-2voto

DarthCoder Points 264

S'il ne s'agit que de cet entier, vous pouvez également utiliser

Interlocked.Increment(count)

(l'espace de noms est System.Threading).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X