web-dev-qa-db-fra.com

Quelle est la différence entre une méthode synchronisée et un bloc synchronisé en Java?

Quelle est la différence entre une méthode synchronisée et un bloc synchronisé en Java?

Je cherchais la réponse sur le net, les gens semblent tellement incertains à propos de celui-ci :-(

Mon point de vue serait qu'il n'y a pas de différence entre les deux, si ce n'est que le bloc synch pourrait être plus localisé et que le verrouillage serait donc de moindre durée ??

Et en cas de verrouillage sur une méthode statique, sur quoi le verrouillage est-il pris? Quel est le sens d'un Lock on Class?

35
Geek

Une méthode synchronisée utilise le récepteur de méthode comme verrou (par exemple, this pour les méthodes non statiques et la classe englobante pour les méthodes statiques). Synchronized blocks utilise l'expression comme un verrou.

Donc, les deux méthodes suivantes sont équivalentes à partir du verrouillage prospectif:

synchronized void mymethod() { ... }

void mymethod() {
  synchronized (this) { ... }
}

Pour les méthodes statiques, la classe sera verrouillée:

class MyClass {
  synchronized static mystatic() { ... }

  static mystaticeq() {
    syncrhonized (MyClass.class) { ... }
  }
}

Pour les blocs synchronisés, vous pouvez utiliser n'importe quel objet non -null comme verrou:

synchronized (mymap) {
  mymap.put(..., ...);
}

Verrouiller la portée

Pour les méthodes synchronisées, le verrou sera maintenu pendant toute l'étendue de la méthode, tandis que dans le bloc synchronized, le verrou ne sera maintenu que pendant la portée de ce bloc (autrement appelée section critique). En pratique, la JVM est autorisée à optimiser en supprimant certaines opérations de l'exécution du bloc synchronized si elle peut prouver que cela peut être fait en toute sécurité.

45
notnoop

Une méthode synchronisée est un raccourci. Ce:

class Something {
    public synchronized void doSomething() {
        ...
    }

    public static synchronized void doSomethingStatic() {
        ...
    }
}

est, à toutes fins pratiques, équivalent à ceci:

class Something {
    public void doSomething() {
        synchronized(this) {
            ...
        }
    }

    public static void doSomethingStatic() {
        synchronized(Something.class) {
            ...
        }
    }
}

(Où Something.class est l'objet classe de la classe Something.)

Donc, en effet, avec un bloc synchronisé, vous pouvez être plus précis sur votre verrou et plus précis sur le moment de l'utiliser, mais à part cela, il n'y a pas de différence.

8
jqno

Oui, c'est une différence. L'autre est que vous pouvez acquérir un verrou sur d'autres objets que this.

3
Henning

La principale différence est la suivante: si vous déclarez une méthode à synchroniser, le corps entier de la méthode devient synchronisé; si vous utilisez le bloc synchronisé, vous pouvez alors entourer uniquement la "section critique" de la méthode dans le bloc synchronisé, tout en laissant le reste de la méthode en dehors du bloc.

Si toute la méthode fait partie de la section critique, il n'y a pas de différence. Si ce n'est pas le cas, utilisez un bloc synchronisé uniquement autour de la section critique. Plus vous avez d’instructions dans un bloc synchronisé, moins vous obtenez de parallélisme global, aussi vous voulez les garder au minimum.

2

Mon point de vue serait qu'il n'y a pas de différence entre les deux, si ce n'est que le bloc synch pourrait être plus localisé et que le verrouillage serait donc de moindre durée ??

Oui. Tu as raison. Contrairement aux méthodes synchronized, les instructions synchronisées doivent spécifier l'objet qui fournit le verrou intrinsèque.

Exemple de tutoriel Java:

public void addName(String name) {
    synchronized(this) {
        lastName = name;
        nameCount++;
    }
    nameList.add(name);
}

Les instructions synchronisées sont également utiles pour améliorer la simultanéité avec une synchronisation fine. Vous pouvez trouver un bon exemple sur la même page de didacticiel pour le cas d'utilisation ci-dessous.

Supposons, par exemple, que la classe MsLunch possède deux champs d'instance, c1 et c2, qui ne sont jamais utilisés ensemble. Toutes les mises à jour de ces champs doivent être synchronized, mais il n'y a aucune raison d'empêcher une mise à jour de c1 d'être imbriquée avec une mise à jour de c2 - et cela réduit ainsi les accès simultanés en créant un blocage inutile. Au lieu d'utiliser des méthodes synchronisées ou d'utiliser le verrou associé, nous créons deux objets uniquement pour fournir des verrous.

Et en cas de verrouillage sur une méthode statique, sur quoi le verrouillage est-il pris? Quel est le sens d'un Lock on Class?

Dans ce cas, le thread acquiert le verrou intrinsèque pour l'objet Class associé à la classe. Ainsi, l'accès aux champs statiques de la classe est contrôlé par un verrou distinct de celui de toute instance de la classe.

Lorsque vous créez une méthode en tant que synchronized (non static):

Il n'est pas possible que deux invocations de méthodes synchronized sur le même objet soient entrelacées. Lorsqu'un thread exécute une méthode synchronisée pour un objet, tous les autres threads appelant des méthodes synchronisées pour le même bloc d'objet (suspendre l'exécution) jusqu'à ce que le premier thread soit terminé avec l'objet.

Si vous créez une méthode en tant que static synchronized:

Il n'est pas possible que deux invocations de méthodes static synchronized sur des objets différents de la même classe s'entrelacent. Lorsqu'un thread exécute une méthode static synchronized pour un objet de classe A, tous les autres threads qui invoquent des méthodes static synchronized sur l'un des objets du bloc de classe A (suspendre l'exécution) jusqu'à la fin du premier thread avec l'exécution de la méthode.

Vous trouvez de meilleures alternatives à la synchronisation dans cette question SE:

Évitez synchronisé (cela) en Java?

0
Ravindra babu

Une méthode synchronisée verrouille l'instance d'objet dans laquelle la méthode est contenue.

Là où un bloc synchronisé peut se verrouiller sur n'importe quel objet, généralement un objet mutex défini comme une variable d'instance. Cela permet de mieux contrôler les verrous en opération.

0
madlep