Que signifie «synchronisé»?

994

J'ai des questions concernant l'utilisation et la signification du synchronizedmot clé.

  • Quelle est la signification du synchronizedmot-clé?
  • Quand les méthodes devraient-elles être synchronized?
  • Qu'est-ce que cela signifie par programmation et logique?
Johanna
la source
1
discussion utile entre hashmap et hashtable, et synchronisation: stackoverflow.com/questions/40471/java-hashmap-vs-hashtable
limc
2
Duplication possible de Comment fonctionne la synchronisation en Java
Marian Paździoch
1
J'ai parcouru tout le lien de documentation depuis le premier commentaire, et je n'ai pas compris jusqu'à ce que j'arrive au dernier paragraphe. Au lieu de coller des liens et de ne rien citer, il peut être utile de coller des liens et d'ajouter un devis est plus utile.
Rakib

Réponses:

878

Le synchronizedmot-clé concerne tous les threads différents lisant et écrivant dans les mêmes variables, objets et ressources. Ce n'est pas un sujet banal en Java, mais voici une citation de Sun:

synchronized Les méthodes permettent une stratégie simple pour éviter les interférences de threads et les erreurs de cohérence de la mémoire: si un objet est visible par plusieurs threads, toutes les lectures ou écritures sur les variables de cet objet sont effectuées via des méthodes synchronisées.

En un très, très petit résumé: lorsque vous avez deux threads qui lisent et écrivent dans la même `` ressource '', disons une variable nommée foo, vous devez vous assurer que ces threads accèdent à la variable de manière atomique. Sans le synchronizedmot - clé, votre thread 1 peut ne pas voir le changement de thread 2 fooou pire, il ne peut être modifié qu'à moitié. Ce ne serait pas ce à quoi vous vous attendez logiquement.

Encore une fois, il s'agit d'un sujet non trivial en Java. Pour en savoir plus, explorez les sujets ici sur SO et les Interwebs sur:

Continuez à explorer ces sujets jusqu'à ce que le nom "Brian Goetz" soit définitivement associé au terme "concurrence" dans votre cerveau.

Stu Thompson
la source
71
Donc, fondamentalement, ce mot clé synchronisé rend vos méthodes thread-safe?
Rigo Vides
82
Le mot clé synchronisé est l'un des outils qui sécurise votre thread de code. Le simple fait d'utiliser synchronized sur une méthode ou une variable en soi peut ou non faire l'affaire. Avoir une compréhension de base du modèle de mémoire Java est vraiment important pour obtenir une concurrence correcte.
Stu Thompson
28
À moins que vous ne soyez Brian Goetz (ou peut-être Jon Skeet), il est presque impossible d'obtenir une concurrence Java correcte avec uniquement les primitives de langage (synchronisées, volatiles). Pour commencer, utilisez le package java.util.concurrent et construisez en plus.
Thilo
12
Plus clairement: les méthodes synchronisées ne peuvent pas être appelées en même temps à partir de plusieurs threads.
peterh
2
@peterh synchronized fait plus que cela, d'où l'explication la plus prolixe
Stu Thompson
294

Eh bien, je pense que nous en avions assez d'explications théoriques, alors considérez ce code

public class SOP {
    public static void print(String s) {
        System.out.println(s+"\n");
    }
}

public class TestThread extends Thread {
    String name;
    TheDemo theDemo;
    public TestThread(String name,TheDemo theDemo) {
        this.theDemo = theDemo;
        this.name = name;
        start();
    }
    @Override
    public void run() {
        theDemo.test(name);
    }
}

public class TheDemo {
    public synchronized void test(String name) {
        for(int i=0;i<10;i++) {
            SOP.print(name + " :: "+i);
            try{
                Thread.sleep(500);
            } catch (Exception e) {
                SOP.print(e.getMessage());
            }
        }
    }
    public static void main(String[] args) {
        TheDemo theDemo = new TheDemo();
        new TestThread("THREAD 1",theDemo);
        new TestThread("THREAD 2",theDemo);
        new TestThread("THREAD 3",theDemo);
    }
}

Remarque: synchronizedbloque l'appel du thread suivant à la méthode test () tant que l'exécution du thread précédent n'est pas terminée. Les threads peuvent accéder à cette méthode un par un. Sans synchronizedtous les threads, vous pouvez accéder à cette méthode simultanément.

Lorsqu'un thread appelle la méthode synchronisée 'test' de l'objet (ici l'objet est une instance de la classe 'TheDemo'), il acquiert le verrou de cet objet, tout nouveau thread ne peut appeler AUCUNE méthode synchronisée du même objet tant que le thread précédent qui avait acquis la serrure ne libère pas la serrure.

La même chose se produit lorsqu'une méthode synchronisée statique de la classe est appelée. Le thread acquiert le verrou associé à la classe (dans ce cas, toute méthode synchronisée non statique d'une instance de cette classe peut être appelée par n'importe quel thread car ce verrou de niveau objet est toujours disponible). Tout autre thread ne pourra appeler aucune méthode synchronisée statique de la classe tant que le verrou au niveau de la classe n'est pas libéré par le thread qui détient actuellement le verrou.

Sortie avec synchronisé

THREAD 1 :: 0
THREAD 1 :: 1
THREAD 1 :: 2
THREAD 1 :: 3
THREAD 1 :: 4
THREAD 1 :: 5
THREAD 1 :: 6
THREAD 1 :: 7
THREAD 1 :: 8
THREAD 1 :: 9
THREAD 3 :: 0
THREAD 3 :: 1
THREAD 3 :: 2
THREAD 3 :: 3
THREAD 3 :: 4
THREAD 3 :: 5
THREAD 3 :: 6
THREAD 3 :: 7
THREAD 3 :: 8
THREAD 3 :: 9
THREAD 2 :: 0
THREAD 2 :: 1
THREAD 2 :: 2
THREAD 2 :: 3
THREAD 2 :: 4
THREAD 2 :: 5
THREAD 2 :: 6
THREAD 2 :: 7
THREAD 2 :: 8
THREAD 2 :: 9

Sortie sans synchronisé

THREAD 1 :: 0
THREAD 2 :: 0
THREAD 3 :: 0
THREAD 1 :: 1
THREAD 2 :: 1
THREAD 3 :: 1
THREAD 1 :: 2
THREAD 2 :: 2
THREAD 3 :: 2
THREAD 1 :: 3
THREAD 2 :: 3
THREAD 3 :: 3
THREAD 1 :: 4
THREAD 2 :: 4
THREAD 3 :: 4
THREAD 1 :: 5
THREAD 2 :: 5
THREAD 3 :: 5
THREAD 1 :: 6
THREAD 2 :: 6
THREAD 3 :: 6
THREAD 1 :: 7
THREAD 2 :: 7
THREAD 3 :: 7
THREAD 1 :: 8
THREAD 2 :: 8
THREAD 3 :: 8
THREAD 1 :: 9
THREAD 2 :: 9
THREAD 3 :: 9
Dheeraj Sachan
la source
7
Excellent exemple, il est bon de connaître la théorie, mais le code est toujours plus précis et complet.
Santi Iglesias
2
@SantiIglesias "Complete"? Nan. Cet exemple illustre le comportement de verrouillage de synchronized, mais la cohérence de la mémoire est ignorée.
Stu Thompson
2
La cohérence de la mémoire @Stu Thompson est le résultat du verrouillage
Dheeraj Sachan
@DheerajSachan Selon cette logique, l'utilisation d'un ReentrantLock entraînerait la cohérence de la mémoire. Ce n'est pas le cas.
Stu Thompson
3
@boltup_im_coding: La méthode start () met le thread dans un état "RUNNABLE", ce qui signifie qu'il est prêt pour l'exécution ou déjà en cours d'exécution. Il peut arriver qu'un autre thread (généralement mais pas nécessairement avec une priorité plus élevée) à l'état Runnable saute la file d'attente et commence à s'exécuter. Dans l'exemple ci-dessus, THREAD 3 s'est avéré avoir un processeur avant THREAD 2.
Sahil J
116

Le synchronizedmot-clé empêche l'accès simultané à un bloc de code ou d'objet par plusieurs threads. Toutes les méthodes de Hashtablesont synchronized, donc un seul thread peut exécuter l'une d'entre elles à la fois.

Lorsque vous utilisez des synchronizedconstructions non similaires HashMap, vous devez créer des fonctionnalités de sécurité des threads dans votre code pour éviter les erreurs de cohérence.

jmort253
la source
81

synchronizedsignifie que dans un environnement multi-thread, un objet ayant des synchronizedméthodes / blocs ne laisse pas deux threads accéder synchronizedsimultanément aux méthodes / blocs de code. Cela signifie qu'un thread ne peut pas lire tandis qu'un autre thread le met à jour.

Le deuxième thread attendra à la place jusqu'à ce que le premier thread termine son exécution. La surcharge est la vitesse, mais l'avantage est la cohérence garantie des données.

Si votre application est monothread, les synchronizedblocs n'offrent aucun avantage.

Codemwnci
la source
54

Le synchronizedmot clé oblige un thread à obtenir un verrou lors de la saisie de la méthode, de sorte qu'un seul thread peut exécuter la méthode en même temps (pour l'instance d'objet donnée, sauf s'il s'agit d'une méthode statique).

Ceci est souvent appelé rendre la classe thread-safe, mais je dirais que c'est un euphémisme. S'il est vrai que la synchronisation protège l'état interne du Vector contre la corruption, cela n'aide généralement pas beaucoup l'utilisateur de Vector.

Considère ceci:

 if (vector.isEmpty()){
     vector.add(data);
 }

Même si les méthodes impliquées sont synchronisées, car elles sont verrouillées et déverrouillées individuellement, deux threads malheureusement synchronisés peuvent créer un vecteur avec deux éléments.

Donc, en fait, vous devez également synchroniser votre code d'application.

La synchronisation au niveau de la méthode étant a) coûteuse lorsque vous n'en avez pas besoin et b) insuffisante lorsque vous avez besoin de synchronisation, il existe désormais des remplacements non synchronisés (ArrayList dans le cas de Vector).

Plus récemment, le package de concurrence a été publié, avec un certain nombre d'utilitaires intelligents qui prennent en charge les problèmes de multi-threading.

Thilo
la source
27

Aperçu

Le mot-clé synchronisé en Java a à voir avec la sécurité des threads, c'est-à-dire lorsque plusieurs threads lisent ou écrivent la même variable.
Cela peut se produire directement (en accédant à la même variable) ou indirectement (en utilisant une classe qui utilise une autre classe qui accède à la même variable).

Le mot-clé synchronisé est utilisé pour définir un bloc de code où plusieurs threads peuvent accéder à la même variable de manière sûre.

Plus profond

Syntaxiquement, le synchronizedmot - clé prend un Objectparamètre comme il est (appelé un objet verrou ), qui est ensuite suivi d'un { block of code }.

  • Lorsque l'exécution rencontre ce mot-clé, le thread actuel essaie de "verrouiller / acquérir / posséder" (faites votre choix) l' objet verrou et exécutez le bloc de code associé une fois le verrou acquis.

  • Toutes les écritures dans les variables à l'intérieur du bloc de code synchronisé sont garanties d'être visibles par tous les autres threads qui exécutent de la même manière le code à l'intérieur d'un bloc de code synchronisé en utilisant le même objet de verrouillage .

  • Un seul thread à la fois peut contenir le verrou, période pendant laquelle tous les autres threads tentant d'acquérir le même objet de verrouillage attendront (suspendent leur exécution). Le verrou sera libéré lorsque l'exécution quittera le bloc de code synchronisé.

Méthodes synchronisées:

L'ajout synchronizedd'un mot clé à une définition de méthode équivaut au corps de méthode entier enveloppé dans un bloc de code synchronisé, l' objet verrou étant this (pour les méthodes par exemple) et ClassInQuestion.getClass() (pour les méthodes de classe) .

- La méthode d'instance est une méthode qui n'a pas de staticmot - clé.
- La méthode de classe est une méthode qui a un staticmot-clé.

Technique

Sans synchronisation, il n'est pas garanti dans quel ordre les lectures et les écritures se produisent, laissant éventuellement la variable avec des ordures.
(Par exemple, une variable peut se retrouver avec la moitié des bits écrits par un thread et la moitié des bits écrits par un autre thread, laissant la variable dans un état qu'aucun des threads n'a tenté d'écrire, mais un désordre combiné des deux.)

Il ne suffit pas de terminer une opération d'écriture dans un thread avant (heure de l'horloge murale) qu'un autre thread ne le lise, car le matériel aurait pu mettre en cache la valeur de la variable, et le thread de lecture verrait la valeur en cache au lieu de ce qui était écrit dans il.

Conclusion

Ainsi, dans le cas de Java, vous devez suivre le modèle de mémoire Java pour vous assurer que les erreurs de thread ne se produisent pas.
En d'autres termes: utilisez la synchronisation, les opérations atomiques ou les classes qui les utilisent pour vous sous les hottes.

Sources

http://docs.oracle.com/javase/specs/jls/se8/html/index.html
Spécification du langage Java®, 2015-02-13

Gima
la source
Désolé, mais j'ai cet exemple et je ne comprends pas la signification: `Integer i1 = Arrays.asList (1,2,3,4,5) .stream (). FindAny (). Get (); synchronized (i1) {Integer i2 = Arrays.asList (6,7,8,9,10) .parallelStream () .sorted () .findAny (). get (); System.out.println (i1 + "" + i2); } `1. Pourquoi avez-vous invoqué le bloc sur la première instance et cette invocation n'a aucun effet sur le code? 2. La seconde instance sera thread-safe, malgré l'invocation du bloc sur la première?
Adryr83
1
@ Adryr83 Si vous avez une question, vous pouvez probablement la poser en publiant une nouvelle question. Mais puisque nous sommes ici, je vais analyser ce que je peux (votre question est un peu difficile à comprendre). D'après ce que je peux dire sur ce morceau de code, il ne semble pas contenir quoi que ce soit qui nécessite une synchronisation. C'est hors contexte. Suggestion: si vous le pouvez, essayez de diviser le code en petits morceaux individuels, puis recherchez des réponses à ce sujet. Il est beaucoup plus facile d'essayer de comprendre les petits problèmes isolés que d'essayer de comprendre un gros bloc de code.
Gima
21

Considérez-le comme une sorte de tourniquet comme vous pourriez le trouver sur un terrain de football. Il y a des flux parallèles de gens qui veulent entrer mais au tourniquet, ils sont «synchronisés». Une seule personne à la fois peut passer. Tous ceux qui veulent passer à travers le feront, mais ils devront peut-être attendre jusqu'à ce qu'ils puissent passer.

Paul
la source
16

Qu'est-ce que le mot clé synchronisé?

Les threads communiquent principalement en partageant l'accès aux champs et aux champs de référence des objets auxquels ils se réfèrent. Cette forme de communication est extrêmement efficace, mais rend possible deux types d'erreurs: les interférences de thread et les erreurs de cohérence de la mémoire . L'outil nécessaire pour éviter ces erreurs est la synchronisation.

Les blocs ou méthodes synchronisés empêchent les interférences de threads et s'assurent que les données sont cohérentes. À tout moment, un seul thread peut accéder à un bloc ou une méthode synchronisée ( section critique ) en acquérant un verrou. Un autre thread attendra la libération du verrou pour accéder à la section critique .

Quand les méthodes sont-elles synchronisées?

Les méthodes sont synchronisées lorsque vous ajoutez synchronizedà la définition ou à la déclaration de méthode. Vous pouvez également synchroniser un bloc de code particulier avec une méthode.

Qu'est-ce que cela signifie pro grammaticalement et logiquement?

Cela signifie qu'un seul thread peut accéder à la section critique en acquérant un verrou. À moins que ce thread ne libère ce verrou, tous les autres threads devront attendre pour acquérir un verrou. Ils n'ont pas accès à la section critique sans avoir à verrouiller.

Cela ne peut pas être fait avec une magie. Il incombe au programmeur d'identifier les sections critiques de l'application et de les protéger en conséquence. Java fournit un cadre pour protéger votre application, mais où et ce que toutes les sections à protéger sont la responsabilité du programmeur.

Plus de détails sur la page de documentation java

Verrous intrinsèques et synchronisation:

La synchronisation est construite autour d'une entité interne connue sous le nom de verrou intrinsèque ou verrou de moniteur. Les verrous intrinsèques jouent un rôle dans les deux aspects de la synchronisation: en imposant un accès exclusif à l'état d'un objet et en établissant des relations préalables qui sont essentielles à la visibilité.

Chaque objet a un verrou intrinsèque qui lui est associé . Par convention, un thread qui a besoin d'un accès exclusif et cohérent aux champs d'un objet doit acquérir le verrou intrinsèque de l'objet avant d'y accéder, puis libérer le verrou intrinsèque lorsqu'il en a fini avec eux.

Un thread est réputé posséder le verrou intrinsèque entre le moment où il a acquis le verrou et relâché le verrou. Tant qu'un thread possède un verrou intrinsèque, aucun autre thread ne peut acquérir le même verrou. L'autre thread se bloquera lorsqu'il tentera d'acquérir le verrou.

Lorsqu'un thread libère un verrou intrinsèque, une relation se produit avant est établie entre cette action et toute acquisition ultérieure du même verrou.

La synchronisation des méthodes a deux effets :

Premièrement, il n'est pas possible que deux invocations de méthodes synchronisées sur le même objet s'entrelacent.

Lorsqu'un thread exécute une méthode synchronisée pour un objet, tous les autres threads qui appellent 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.

Deuxièmement, lorsqu'une méthode synchronisée se termine, elle établit automatiquement une relation passe-avant avec toute invocation ultérieure d'une méthode synchronisée pour le même objet.

Cela garantit que les modifications de l'état de l'objet sont visibles pour tous les threads.

Recherchez d'autres alternatives à la synchronisation dans:

Évitez synchronisé (ce) en Java?

Ravindra babu
la source
11

Synchronized normal methodéquivalent à Synchronized statement(utiliser ceci)

class A {
    public synchronized void methodA() {
        // all function code
    }

    equivalent to

    public void methodA() {
        synchronized(this) {
             // all function code
        }
    } 
}

Synchronized static methodéquivalent à Synchronized statement(classe d'utilisation)

class A {
    public static synchronized void methodA() {
        // all function code
    }

    equivalent to

    public void methodA() {
        synchronized(A.class) {
             // all function code
        }
    } 
}

Instruction synchronisée (à l'aide d'une variable)

class A {
    private Object lock1 = new Object();

    public void methodA() {
        synchronized(lock1 ) {
             // all function code
        }
    } 
}

Pour synchronized, nous avons les deux Synchronized Methodset Synchronized Statements. Cependant, Synchronized Methodsest similaire à Synchronized Statementsdonc nous avons juste besoin de comprendre Synchronized Statements.

=> Fondamentalement, nous aurons

synchronized(object or class) { // object/class use to provides the intrinsic lock
   // code 
}

Voici 2 pense que aider à comprendre synchronized

  • Chaque objet / classe a un intrinsic lockassocié.
  • Lorsqu'un thread appelle a synchronized statement, il acquiert automatiquement le intrinsic lockpour cet synchronized statement'sobjet et le libère lorsque la méthode revient. Tant qu'un thread possède un intrinsic lock, aucun autre thread ne peut acquérir le même verrou => thread-safe.

=> Quand a thread Ainvoque synchronized(this){// code 1}=> tout le code de bloc (à l'intérieur de la classe) où have synchronized(this)et tout synchronized normal method(à l'intérieur de la classe) est verrouillé car SAME se verrouille. Il s'exécutera après thread Adéverrouillage ("// code 1" terminé).

Ce comportement est similaire à synchronized(a variable){// code 1}ou synchronized(class).

SAME LOCK => lock (ne dépend pas de quelle méthode? Ou de quelles instructions?)

Utiliser une méthode synchronisée ou des instructions synchronisées?

Je préfère synchronized statementscar il est plus extensible. Par exemple, à l'avenir, vous aurez seulement besoin de synchroniser une partie de la méthode. Par exemple, vous avez 2 méthodes synchronisées et elles n'ont aucune pertinence les unes par rapport aux autres, mais lorsqu'un thread exécute une méthode, il bloque l'autre méthode (il peut empêcher l'utilisation synchronized(a variable)).

Cependant, appliquer la méthode synchronisée est simple et le code semble simple. Pour certaines classes, il n'y a qu'une seule méthode synchronisée, ou toutes les méthodes synchronisées de la classe sont pertinentes les unes par rapport aux autres => nous pouvons utiliser synchronized methodpour rendre le code plus court et facile à comprendre

Remarque

(ce n'est pas pertinent pour beaucoup synchronized, c'est la différence entre objet et classe ou non-statique et statique).

  • Lorsque vous utilisez synchronizedou la méthode normale ou synchronized(this)ou synchronized(non-static variable)il synchronisera la base sur chaque instance d'objet.
  • Lorsque vous utilisez synchronizedou une méthode statique ou synchronized(class)ou synchronized(static variable)il synchronisera la base sur la classe

Référence

https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html https://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html

J'espère que ça aide

Phan Van Linh
la source
11

Voici une explication des Java Tutorials .

Considérez le code suivant:

public class SynchronizedCounter {
    private int c = 0;

    public synchronized void increment() {
        c++;
    }

    public synchronized void decrement() {
        c--;
    }

    public synchronized int value() {
        return c;
    }
}

si countest une instance de SynchronizedCounter, alors la synchronisation de ces méthodes a deux effets:

  • Premièrement, il n'est pas possible que deux invocations de méthodes synchronisées sur le même objet s'entrelacent. Lorsqu'un thread exécute une méthode synchronisée pour un objet, tous les autres threads qui appellent 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.
  • Deuxièmement, lorsqu'une méthode synchronisée se termine, elle établit automatiquement une relation passe-avant avec toute invocation ultérieure d'une méthode synchronisée pour le même objet. Cela garantit que les modifications de l'état de l'objet sont visibles pour tous les threads.
Shahryar Saljoughi
la source
9

À ma connaissance, la synchronisation signifie essentiellement que le compilateur écrit un monitor.enter et un monitor.exit autour de votre méthode. En tant que tel, il peut être sûr pour les threads selon la façon dont il est utilisé (ce que je veux dire, c'est que vous pouvez écrire un objet avec des méthodes synchronisées qui n'est pas threadsafe en fonction de ce que fait votre classe).

Spence
la source
5

Ce qui manque aux autres réponses est un aspect important: les barrières de mémoire . La synchronisation des threads se compose essentiellement de deux parties: la sérialisation et la visibilité. Je conseille à tout le monde de google pour "barrière de mémoire jvm", car c'est un sujet non trivial et extrêmement important (si vous modifiez les données partagées accessibles par plusieurs threads). Cela fait, je conseille de regarder les classes du package java.util.concurrent qui aident à éviter d'utiliser la synchronisation explicite, ce qui contribue à garder les programmes simples et efficaces, peut-être même à empêcher les blocages.

Un tel exemple est ConcurrentLinkedDeque . Avec le modèle de commande, il permet de créer des threads de travail hautement efficaces en remplissant les commandes dans la file d'attente simultanée - aucune synchronisation explicite requise, aucun blocage possible, aucun sommeil explicite () nécessaire, il suffit d'interroger la file d'attente en appelant take ().

En bref: la "synchronisation de la mémoire" se produit implicitement lorsque vous démarrez un thread, un thread se termine, vous lisez une variable volatile, vous déverrouillez un moniteur (laissez un bloc / une fonction synchronisé), etc. Cette "synchronisation" affecte (dans un sens) les vidages ") toutes les écritures effectuées avant cette action particulière. Dans le cas du ConcurrentLinkedDeque susmentionné , la documentation "dit":

Effets de cohérence de la mémoire: comme pour les autres collections simultanées, les actions dans un thread avant de placer un objet dans un ConcurrentLinkedDeque se produisent avant les actions postérieures à l'accès ou à la suppression de cet élément du ConcurrentLinkedDeque dans un autre thread.

Ce comportement implicite est un aspect quelque peu pernicieux car la plupart des programmeurs Java sans grande expérience prendront beaucoup comme donné à cause de cela. Et puis soudainement tomber sur ce fil après que Java ne fait pas ce qu'il est censé faire dans la production où il y a une charge de travail différente - et il est assez difficile de tester les problèmes de concurrence.

user1050755
la source
3

Synchronisé signifie simplement que plusieurs threads s'ils sont associés à un seul objet peuvent empêcher une lecture et une écriture incorrectes si un bloc synchronisé est utilisé sur un objet particulier. Pour vous donner plus de clarté, prenons un exemple:

class MyRunnable implements Runnable {
    int var = 10;
    @Override
    public void run() {
        call();
    }

    public void call() {
        synchronized (this) {
            for (int i = 0; i < 4; i++) {
                var++;
                System.out.println("Current Thread " + Thread.currentThread().getName() + " var value "+var);
            }
        }
    }
}

public class MutlipleThreadsRunnable {
    public static void main(String[] args) {
        MyRunnable runnable1 = new MyRunnable();
        MyRunnable runnable2 = new MyRunnable();
        Thread t1 = new Thread(runnable1);
        t1.setName("Thread -1");
        Thread t2 = new Thread(runnable2);
        t2.setName("Thread -2");
        Thread t3 = new Thread(runnable1);
        t3.setName("Thread -3");
        t1.start();
        t2.start();
        t3.start();
    }
}

Nous avons créé deux objets de classe MyRunnable, runnable1 étant partagé avec le thread 1 et le thread 3 & runnable2 étant partagé avec le thread 2 uniquement. Maintenant, lorsque t1 et t3 commencent sans synchronisation, la sortie PFB suggère que les deux threads 1 et 3 affectent simultanément la valeur var alors que pour le thread 2, var a sa propre mémoire.

Without Synchronized keyword

    Current Thread Thread -1 var value 11
    Current Thread Thread -2 var value 11
    Current Thread Thread -2 var value 12
    Current Thread Thread -2 var value 13
    Current Thread Thread -2 var value 14
    Current Thread Thread -1 var value 12
    Current Thread Thread -3 var value 13
    Current Thread Thread -3 var value 15
    Current Thread Thread -1 var value 14
    Current Thread Thread -1 var value 17
    Current Thread Thread -3 var value 16
    Current Thread Thread -3 var value 18

À l'aide de Synchronzied, le thread 3 attend la fin du thread 1 dans tous les scénarios. Il y a deux verrous acquis, un sur runnable1 partagé par le thread 1 et le thread 3 et un autre sur runnable2 partagé par le thread 2 uniquement.

Current Thread Thread -1 var value 11
Current Thread Thread -2 var value 11
Current Thread Thread -1 var value 12
Current Thread Thread -2 var value 12
Current Thread Thread -1 var value 13
Current Thread Thread -2 var value 13
Current Thread Thread -1 var value 14
Current Thread Thread -2 var value 14
Current Thread Thread -3 var value 15
Current Thread Thread -3 var value 16
Current Thread Thread -3 var value 17
Current Thread Thread -3 var value 18
paras4all
la source
Synchronisé signifie encore plus que cela: il a un impact profond sur la barrière de la mémoire.
user1050755
1

synchronisé simple signifie qu'aucun thread ne peut accéder simultanément au bloc / à la méthode. Lorsque nous disons que n'importe quel bloc / méthode d'une classe est synchronisé, cela signifie qu'un seul thread peut y accéder à la fois. En interne, le thread qui essaie d'y accéder prend d'abord un verrou sur cet objet et tant que ce verrou n'est pas disponible, aucun autre thread ne peut accéder aux méthodes / blocs synchronisés de cette instance de la classe.

Notez qu'un autre thread peut accéder à une méthode du même objet qui n'est pas définie pour être synchronisée. Un thread peut libérer le verrou en appelant

Object.wait()
Aniket Thakur
la source
0

synchronizedblock en Java est un moniteur en multithreading. synchronizedbloc avec le même objet / classe peut être exécuté par un seul thread, tous les autres attendent. Cela peut aider dans la race conditionsituation où plusieurs threads essaient de mettre à jour la même variable (la première étape utilise volatileAbout )

Java 5étendu synchronizeden soutenant happens-before[À propos]

Un déverrouillage (bloc synchronisé ou sortie de méthode) d'un moniteur se produit avant chaque verrou ultérieur (bloc synchronisé ou entrée de méthode) de ce même moniteur.

La prochaine étape est java.util.concurrent

volatile vs synchronisé

yoAlex5
la source
-6

synchronized est un mot clé en Java qui est utilisé pour faire se produire avant la relation dans un environnement multithreading pour éviter les incohérences de mémoire et les erreurs d'interférence de thread.

Sharad
la source