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

cette question a déjà une réponse ici:

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

j'ai été cherchant la réponse sur le Net, les gens semblent être si incertains à propos de celui-ci: - (

mon point de vue serait qu'il n'y a pas de différence entre les deux, sauf que le bloc de synchronisation pourrait être plus localisée dans la portée et donc la serrure sera de moins de temps ??

et en cas de verrouillage sur une méthode statique, sur quoi prend la serrure ? Quelle est la signification d'un verrou sur la classe ?

35
demandé sur Ravindra babu 2009-07-19 17:45:45

6 réponses

une méthode synchronisée utilise le récepteur de méthode comme une serrure (i.e. this pour les méthodes non statiques, et la classe enveloppante pour les méthodes statiques). Synchronized blocks utilise l'expression comme une serrure.

les deux méthodes suivantes sont donc équivalentes à la méthode prospective de verrouillage:

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 Non - null objet comme Serrure:

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

Lock portée

pour les méthodes synchronisées, la serrure sera maintenue tout au long du champ d'application de la méthode, tandis que dans le bloc synchronized , la serrure ne sera maintenue que pendant le champ d'application de ce bloc (aussi appelé section critique). En pratique, la JVM est autorisée à optimiser en retirant certaines opérations de l'exécution du bloc synchronized si elle peut prouver qu'elle peut être effectuée en toute sécurité.

45
répondu notnoop 2015-11-04 00:43:15

une méthode synchronisée est abrégée. Ceci:

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 de la classe Something .)

donc en effet, avec un bloc synchronisé, vous pouvez être plus précis à propos de votre serrure, et plus précis sur le moment où vous voulez l'utiliser, mais à part ça, il n'y a aucune différence.

8
répondu jqno 2009-07-19 14:35:35

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

3
répondu Henning 2009-07-19 13:50:08

la différence clé est celle-ci: si vous déclarez qu'une méthode doit être synchronisée, alors le corps entier de la méthode devient synchronisé; si vous utilisez le bloc synchronisé, cependant, vous pouvez entourer juste 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 l'ensemble de la méthode fait partie de la section critique, alors il n'y a effectivement aucune différence. Si ce n'est pas le cas, alors vous devriez utilisez un bloc synchronisé autour de la section critique. Plus vous avez de déclarations dans un bloc synchronisé, moins vous obtenez de parallélisme global, donc vous voulez les garder au minimum.

2
répondu Michael Aaron Safyan 2009-07-19 13:59:30

une méthode synchronisée se bloque sur l'instance de l'objet dans laquelle la méthode est contenue.

où comme un bloc synchronisé peut se verrouiller sur N'importe quel objet - typiquement un obect mutex défini comme une variable d'instance. Cela permet plus de contrôle sur ce que les serrures sont en fonctionnement.

0
répondu madlep 2009-07-19 13:53:16

mon point de vue serait qu'il n'y a pas de différence entre les deux, sauf que le bloc de synchronisation pourrait être plus localisé dans la portée et donc la serrure sera de moins de temps ??

Oui. Vous êtes de droite. Contrairement aux méthodes synchronized , les instructions synchronisées doivent spécifier l'objet qui fournit le verrouillage intrinsèque.

exemple tiré du tutoriel java:

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

déclarations synchronisées sont également utiles pour améliorer la simultanéité avec une synchronisation à grain fin. Vous pouvez trouver un bon exemple sur la même page de tutoriel pour cas d'utilisation ci-dessous.

supposons, par exemple, que la classe MsLunch comporte 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 entrelacée avec une mise à jour de c2 - et cela réduit la concurrence en créant des blocages inutiles. au lieu d'utiliser des méthodes synchronisées ou d'utiliser la serrure associée, nous créons deux objets uniquement pour fournir des serrures .

et en cas de verrouillage sur une méthode statique, sur quoi prend la serrure ? Quelle est la signification d'un verrou sur la classe ?

dans ce cas, le fil acquiert la serrure intrinsèque de l'objet de la classe associé à la classe. Ainsi l'accès aux champs statiques de la classe est contrôlé par un verrou qui est distincte de la serrure pour toute instance de la classe.

Lorsque vous effectuez une méthode comme synchronisé ( non static ) :

il n'est pas possible d'intercaler deux invocations de la méthode synchronized sur le même objet. Quand un thread exécute une méthode synchronisée pour un objet, tous les autres threads qui invoquent des méthodes synchronisées pour le même bloc d'objet (suspendre l'exécution) jusqu'à ce que le premier fil soit fait avec l'objet.

si vous faites une méthode comme static synchronized :

il n'est pas possible d'intercaler deux invocations de la méthode static synchronized sur différents objets de la même classe. Lorsqu'un thread exécute une méthode static synchronized pour un objet de la classe a, tous les autres threads qui invoquent les méthodes static synchronized sur l'un quelconque des objets de la Classe A (SUSPENDRE l'exécution) jusqu'à ce que le premier thread soit fait avec la méthode exécution.

Vous trouver de meilleures solutions pour la synchronisation de cette SE a la question:

Evite synchronized (this) in Java?

0
répondu Ravindra babu 2017-05-23 11:47:16