4 votes

les membres statiques lorsqu'ils sont utilisés dans une méthode ou un bloc synchronisé en java

Lorsque j'utilise une méthode synchronisée sur une méthode d'instance, le moniteur est associé à 'this'. En revanche, lorsque j'utilise une méthode synchronisée sur une méthode de classe (statique), le moniteur est associé à l'objet de classe. Que se passe-t-il lorsque j'ai une variable statique utilisée dans une méthode non statique ? Sera-t-elle synchronisée ?

Par exemple,

public class A{

   public static int reg_no = 100;

   public synchronized void registration(){

      A.reg_no = some operation...

   }

}

Dans le cas ci-dessus, que va-t-il se passer pour la variable statique reg_no si deux ou plusieurs threads sont en compétition pour la méthode registration() ?

4voto

Greg Hewgill Points 356191

Lorsqu'une fonction membre est annotée avec synchronized la méthode est synchronisée sur le instance de l'objet. Si vous voulez effectuer une synchronisation sur une variable statique, vous devez effectuer une synchronisation manuelle sur la variable objet de classe :

public synchronized void registration() {
    synchronized (A.class) {
        A.reg_no = some operation ...
    }
}

Notez que ce qui précède permet d'obtenir deux verrous, ce qui peut conduire à blocages si un autre code obtient les deux mêmes verrous dans l'autre ordre. Vous pouvez supprimer synchronized de la méthode, laissant seulement synchronized (A.class) .

2voto

Stevie Points 1515

(Révisé après une réflexion plus approfondie)

Pour l'exemple présenté ci-dessus, vous pouvez vous en sortir en déclarant votre static int comme volatile, comme l'a suggéré Punkers.

Dans le cas général cependant - par exemple si votre variable statique était un objet avec un état mutable ...

La méthode d'instance synchronisée signifie que seul le thread détenant le verrou objet-instance est autorisé à progresser dans cette méthode de cette instance de la classe A, et que lorsque le thread termine dans la méthode et libère le verrou, tout autre thread entrant dans un bloc synchronisé utilisant le même verrou "verra" les modifications que vous avez apportées.

Elle le fait no empêcher que des modifications soient apportées à la variable statique par un autre thread qui :

  • assigne une nouvelle valeur à la variable statique directement depuis l'extérieur de la classe A (la variable est publique !)
  • appelle une méthode statique de la classe A (synchronisée ou non) qui réassigne la variable statique, car elle utilisera un verrou différent
  • appelle une méthode d'instance non synchronisée de la classe A

L'utilisation de méthodes synchronisées est généralement un peu dangereuse - elles peuvent conduire à des blocages parce que le verrou peut être pris à l'extérieur par un autre code qui utilise votre classe/instance comme cible d'un bloc synchronisé :

synchronized (objectOfTypeA) { ... } // takes the instance lock

ou

synchronized (A.getClass()) { ... } // takes the class lock

Une meilleure approche pourrait être de rendre la variable statique privée, d'ajouter une variable locale privée à utiliser comme verrou (afin qu'elle ne puisse pas être verrouillée en externe), et d'utiliser le verrou local privé dans des blocs synchronisés dans vos méthodes :

public class A {

    private static int reg_no = 100;
    private static Object lock = new Object();

    public void registration(){
        synchronized(lock) {
            reg_no = some operation...
        }
    }

    public static int getRegNo() {
        synchronized(lock) {
            return reg_no;
        }
    }
}

1voto

Bozho Points 273663

L'accès aux variables (statiques ou d'instance) n'est pas synchronisé. La synchronisation de la méthode permet d'éviter les situations de concurrence pour une seule instance, quelle que soit la variable (statique ou d'instance).

Si vous voulez protéger des instances multiples, vous devez synchroniser sur le littéral de la classe, mais cela ne semble vraiment pas correct.

0voto

Gabor Kulcsar Points 1851

Non, vous devez synchroniser la méthode avec la classe, par exemple. synchronized(A.class) .

0voto

punkers Points 59

Au lieu d'ajouter un autre bloc syncronisé à l'intérieur de la méthode syncronisée, je déclarerais la variable statique comme volatile, si votre problème est de partager cette variable avec d'autres threads.

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