Question

J'ai quelques questions concernant l'utilisation et la signification du mot-clé synchronized.

  • Quelle est la signification du mot-clé synchronized?
  • Quand faut-il être des méthodes synchronized?
  • Qu'est-ce que cela signifie et logiquement programmation?
Était-ce utile?

La solution

Le mot-clé synchronized est tout au sujet de différents threads lecture et l'écriture aux mêmes variables, des objets et des ressources. Ce n'est pas un sujet trivial en Java, mais voici une citation de Sun:

  

méthodes de synchronized permettent simple   stratégie de prévention de fil   interférences et la cohérence mémoire   erreurs: si un objet est visible   plus d'un fil, toutes les lectures ou   écrit aux variables de cet objet sont   effectuée par des méthodes synchronisées.

Dans un très petit mot: Lorsque vous avez deux fils qui sont la lecture et l'écriture à la même « ressource », dire une variable nommée foo, vous devez vous assurer que ces fils accéder à la la variable d'une manière atomique. Sans le mot-clé synchronized, votre fil 1 ne peut pas voir le fil changement 2 fait à foo, ou pire encore, il ne peut être changé la moitié. Ce ne serait pas ce que vous attendez logiquement.

Encore une fois, ceci est un sujet non trivial en Java. Pour en savoir plus, d'explorer des sujets ici sur le SO et les Interwebs sur:

explorer ces sujets Gardez jusqu'à ce que le nom "Brian Goetz" est définitivement associé au terme "concurrency" dans votre cerveau.

Autres conseils

Eh bien, je pense que nous avons eu assez d'explications théoriques, alors pensez à 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: Les blocs de synchronized le prochain appel de fil à tester la méthode () tant que l'exécution du thread précédent n'est pas terminé. Les threads peuvent accéder à cette méthode un à la fois. Sans synchronized tous les threads peuvent accéder à cette méthode simultanément.

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

chose semblable se produit quand une méthode synchronisée statique de la classe est appelée. Le fil acquiert le verrou associé à la classe (dans ce cas, quelle méthode synchronisée non statique d'une instance de cette classe peut être appelé par un fil, car ce verrou au niveau de l'objet est toujours disponible). Toute autre thread ne sera pas en mesure d'appeler une méthode synchronisée statique de la classe tant que le verrou de niveau de classe n'est pas libéré par le fil qui détient actuellement le verrou.

sortie avec synchronisation

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

Le mot-clé synchronized empêche l'accès simultané à un bloc de code ou d'un objet par plusieurs threads. Par défaut, un Hashtable est synchronized, donc un seul thread peut accéder à la table à la fois.

Sur l'utilisation des non-synchronized construit comme HashMap, vous devez construire des dispositifs de sécurité de fil dans votre code pour éviter les erreurs de cohérence de mémoire.

synchronized signifie que dans un environnement multi-tâche, un objet ayant la méthode de synchronized (s) / bloc (s) ne laisse pas deux fils pour accéder à la méthode de synchronized (s) / bloc (s) de code en même temps. Cela signifie qu'un fil ne peut pas lire alors un autre thread, il met à jour.

Le deuxième thread au lieu d'attendre jusqu'à ce que le premier thread termine son exécution. Les frais généraux est la vitesse, mais l'avantage est garanti la cohérence des données.

Si votre application est seul thread cependant, des blocs de synchronized ne fournit pas de prestations.

Le mot-clé synchronized provoque un fil pour obtenir un verrouillage en entrant dans le procédé, de sorte qu'un seul fil peut exécuter le procédé en même temps (pour l'instance d'objet donné, sauf si elle est une méthode statique).

Ceci est souvent appelé faisant la classe thread-safe, mais je dirais que c'est un euphémisme. Il est vrai que la synchronisation protège l'état interne du vecteur de se corrompre, cela ne facilite généralement l'utilisateur de bien Vector.

Considérez ceci:

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

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

Donc, en effet, vous devez synchroniser dans votre code d'application ainsi.

Parce que la synchronisation au niveau de la méthode est) coûteuse lorsque vous n'avez pas besoin et b) insuffisante lorsque vous avez besoin de synchronisation, il y a maintenant des remplacements de l'ONU synchronisé (ArrayList dans le cas de Vector).

Plus récemment, le paquet a été libéré concurrency, avec un certain nombre de services publics intelligents qui prennent soin des problèmes de traitement multithread.

Aperçu

mot-clé synchronized en Java doit faire avec fil de sécurité, qui est, 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 dans lequel plusieurs fils peuvent accéder à la même variable d'une manière sûre.

Deeper

Syntaxe-sage le mot-clé synchronized prend un Object comme il est paramètre (appelé un objet de verrouillage ), qui est ensuite suivie d'une { block of code }.

  • Lorsque l'exécution rencontre ce mot-clé, le thread courant tente de « verrouillage / acquisition / propre » (faites votre choix) Verouiller et exécuter le bloc associé de code après la serrure été acquis.

  • Toutes les écritures à des variables à l'intérieur du bloc de code synchronisé sont garantis pour être visible à tout autre thread qui exécute la même façon code dans un bloc de code synchronisé en utilisant le même objet verrou .

  • Un seul thread à la fois peut maintenir le verrou, au cours de laquelle tous les autres threads essayant d'acquérir le même Verouiller attendront (pause leur exécution). Le verrouillage sera libéré lorsque l'exécution sort du bloc de code synchronisé.

Méthodes Synchronisé:

Ajout de mot-clé synchronized à une définition de méthode est égal à l'ensemble du corps de procédé étant enveloppé dans un bloc de code synchronisé avec le objet verrou étant this (pour les méthodes d'instance) et ClassInQuestion.getClass() (pour les méthodes de classe) .

- méthode d'instance est une méthode qui n'a pas de mot-clé static . - Méthode de classe est une méthode qui a mot-clé static

.

Technique

Sans synchronisation, il est pas garanti dans quel ordre les lectures et écritures se produire, ce qui laisse peut-être la variable avec les ordures.
(Par exemple une variable pourrait se retrouver avec la moitié des bits écrits par un fil et la moitié des bits écrits par un autre fil, laissant la variable dans un état que ni des fils essayé d'écrire, mais un mess de les deux.)

Il ne suffit pas de terminer une opération d'écriture dans un fil avant (temps horloge murale) un autre thread lit, parce que le matériel aurait mis en cache la valeur de la variable, et le fil de la lecture verrait la valeur mise en cache au lieu de ce a été écrit il.

Conclusion

Ainsi, dans le cas de Java, vous devez suivre le modèle Java mémoire pour vous assurer que les erreurs de filetage ne se produisent pas.
En d'autres termes:. Synchronisation utilisation, les opérations atomiques ou des classes qui les utilisent pour vous sous les capots

  

Sources

     

http://docs.oracle.com/javase/specs/jls/se8 /html/index.html
   Java® Language Specification, 13/02/2015

Pensez-y comme une sorte de tourniquet comme vous trouverez peut-être à un terrain de football. Il y a parallèles de personnes vapeurs qui veulent entrer mais au tourniquet, ils sont « synchronisés ». Une seule personne à la fois peut passer à travers. Tous ceux qui veulent passer à travers le fera, mais ils peuvent avoir à attendre jusqu'à ce qu'ils puissent passer.

  

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

Fils communiquent principalement par le partage de l'accès aux champs et les objets de référence des champs se réfèrent. Cette forme de communication est extrêmement efficace, mais fait deux types d'erreurs possibles: interférence du fil et des erreurs de cohérence mémoire . L'outil nécessaire pour éviter ces erreurs est la synchronisation.

blocs ou méthodes Synchronisé empêche les interférences de fil et assurez-vous que les données sont cohérentes. A tout moment, un seul fil peut accéder à un bloc synchronisé ou procédé ( section critique ) en faisant l'acquisition d'un verrou. Autre fil (s) attendra la libération de verrouillage d'accès section critique .

  

sont des méthodes synchronisées?

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

  

Qu'est-ce que cela signifie programmaticalement et logiquement?

Cela signifie que seul thread peut accéder section critique par l'acquisition d'un verrou. À moins que cette version de fil cette serrure, tous les autres fil (s) devra attendre d'acquérir un verrou. Ils n'ont pas accès pour entrer dans section critique avec verrouillage sur l'acquisition.

Cela ne peut pas être fait avec une magie. Il est responsable de programmeur pour identifier les section critique (s) dans l'application et conservez-le en conséquence. Java fournit un cadre pour protéger votre application, mais où et ce que toutes les sections à la responsabilité est gardée du programmeur.

Plus de détails de la page de documentation java de rel="noreferrer">

verrous internes et la synchronisation:

  

La synchronisation est construit autour d'une entité interne connue sous le verrou interne ou verrouillage du moniteur. les verrous internes jouent un rôle dans les deux aspects de la synchronisation:. appliquer un accès exclusif à l'état d'un objet et l'établissement passe-avant les relations qui sont essentielles à la visibilité

Chaque objet a un verrou intrinsèque associé . Par convention, un fil qui a besoin d'un accès exclusif et cohérente aux champs d'un objet doit acquérir un verrou intrinsèque de l'objet avant d'y accéder, puis relâchez le verrou intrinsèque quand il est fait avec eux.

Un fil est dit posséder le verrou intrinsèque entre le moment où il a acquis le verrou et libéré le verrou. Tant que un fil possède un verrou intrinsèque, aucun autre thread ne peut acquérir le même verrou. L'autre thread va bloquer quand il tente d'acquérir le verrou.

  

Lorsqu'un thread libère un verrou interne, une relation se passe-avant est établie entre cette action et une acquisition ultérieure de la même serrure.

Faire des méthodes synchronisées a deux effets :

  

Tout d'abord, il est impossible pour deux appels de méthodes synchronisées sur le même objet à entrelacer.

Quand un fil exécute une méthode synchronisée pour un objet, tous les autres fils qui font appel à des méthodes synchronisées pour le même bloc d'objet (suspendre l'exécution) jusqu'à ce que le premier fil est fait avec l'objet.

  

En second lieu, lorsqu'une sorties de méthode synchronisée, il établit automatiquement une relation qui se passe, avant toute invocation ultérieure d'une méthode synchronisée pour le même objet.

Cela garantit que les changements à l'état de l'objet sont visibles à toutes les discussions.

Rechercher d'autres alternatives à la synchronisation dans:

Évitez synchronisée (cela) en Java?

Voici une explication de Java Tutoriels .

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 count est une instance de SynchronizedCounter, puis faire ces méthodes synchronisées a deux effets:

     
      
  • Tout d'abord, il est impossible pour deux appels de méthodes synchronisées sur le même objet à entrelacer. Quand un fil exécute une méthode synchronisée pour un objet, tous les autres fils qui font appel à des méthodes synchronisées pour le même bloc d'objet (suspendre l'exécution) jusqu'à ce que le premier fil est fait avec l'objet.
  •   
  • En second lieu, lorsqu'une sorties de méthode synchronisée, il établit automatiquement une relation qui se passe, avant toute invocation ultérieure d'une méthode synchronisée pour le même objet. Cela garantit que les changements à l'état de l'objet sont visibles à tous les threads.
  •   

Synchronized normal method équivalent à Synchronized statement (utiliser)

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
        }
    } 
}

Déclaration Synchronisé (variable en utilisant)

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

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

Pour synchronized, nous avons tous les deux Synchronized Methods et Synchronized Statements. Cependant, Synchronized Methods est similaire à Synchronized Statements donc nous avons juste besoin de comprendre Synchronized Statements.

=> Fondamentalement, nous aurons

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

est 2 pense ici que la compréhension de l'aide synchronized

  • Chaque objet / classe ont un intrinsic lock qui lui est associée.
  • Lorsqu'un thread appelle une synchronized statement, il acquiert automatiquement la intrinsic lock pour cet objet de synchronized statement's et le libère lorsque les retours de procédé. Tant qu'un fil possède un intrinsic lock, AUCUN autre fil peut acquérir le SAME verrouillage => thread-safe.

=> Lorsqu'un thread A invoque synchronized(this){// code 1} => tout le code de bloc (à l'intérieur de classe) où ont synchronized(this) et tous synchronized normal method (à l'intérieur de classe) est bloqué parce que SAME verrouillage. Il exécutera après thread A déverrouillage ( "// Code 1" fini).

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

VERROUILLAGE SAME => serrure (ne dépend pas de la méthode? Ou qui états?)

Utilisez la méthode synchronisée ou déclarations synchronisées?

Je préfère synchronized statements parce qu'il est plus extensible. Exemple, à l'avenir, vous avez seulement besoin synchronisé une partie de la méthode. Exemple, vous avez 2 méthode synchronisée et ne pas correspondant à l'autre, mais lorsqu'un thread exécuter une méthode, il bloque l'autre méthode (il peut empêcher l'utilisation par synchronized(a variable)).

Cependant, appliquer la méthode synchronisée est simple et le code semble simple. Pour une classe, il seulement 1 méthode synchronisée, ou toutes les méthodes synchronisées dans la classe concernée à l'autre => nous pouvons utiliser synchronized method pour faire court et facile à comprendre le code

Note

(il ne concerne pas beaucoup à synchronized, il est la différence entre l'objet et la classe ou pas statique et statique).

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

Référence

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

Je espère que ça aide

Pour ma compréhension synchronisé signifie essentiellement que le compilateur écrire un Monitor.Enter et monitor.exit autour de votre méthode. À ce titre, il peut être thread-safe en fonction de la façon dont il est utilisé (ce que je veux dire est que vous pouvez écrire un objet avec des méthodes synchronisées qui ThreadSafe pas en fonction de ce que votre classe ne).

Ce que les autres réponses manquent est un aspect important: barrières de mémoire . La synchronisation des threads se compose essentiellement de deux parties: sérialisation et la visibilité. Je conseille à tous à Google pour « barrière de mémoire jvm », comme il est un sujet non trivial et extrêmement important (si vous modifiez les données partagées accessibles par plusieurs threads). Après avoir fait cela, je vous conseille de regarder les cours de package java.util.concurrent qui aident à éviter d'utiliser la synchronisation explicite, ce qui contribue à maintenir des programmes simples et efficaces, peut-être même prévenir les blocages.

Un tel exemple est ConcurrentLinkedDeque . En collaboration avec le il permet de créer des threads de production à haut rendement en bourrant les commandes dans la file d'attente en même temps -. pas de synchronisation explicite nécessaire, pas possible blocages, pas de sommeil explicite () nécessaire, juste interroger la file d'attente en appelant prendre ()

En bref: « la synchronisation de la mémoire » arrive implicitement lorsque vous démarrez un fil, un bouts de fil, vous lisez une variable volatile, vous débloquez un moniteur (laisser un bloc synchronisé / fonction), etc. Cette "synchronisation" affecte (dans un sens "flushes") toutes les écritures fait avant cette action particulière. Dans le cas de la ConcurrentLinkedDeque , la documentation "dit":

  

Effets de cohérence de la mémoire: Comme avec d'autres collections simultanées,   actions dans un fil avant de placer un objet dans un   ConcurrentLinkedDeque arriver avant- les actions suivantes à l'accès   ou le retrait dudit élément de la ConcurrentLinkedDeque dans un autre   fil.

Ce comportement implicite est un aspect quelque peu pernicieux parce que la plupart des programmeurs Java sans beaucoup d'expérience vont simplement prendre beaucoup comme indiqué à cause de cela. Et puis tout à coup tomber par hasard sur ce fil après Java ne fait pas ce qu'il est « censé » faire dans la production où il y a une charge de travail différent -. Et il est assez difficile de tester les problèmes de concurrence

synchronisé signifie simplement que plusieurs threads si elle est associée avec un objet unique peut empêcher lecture sale et d'écriture si le bloc synchronisé est utilisé sur un objet particulier. Pour vous donner plus de clarté, permet de prendre 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 fil 1 et le fil 3 & runnable2 étant partagé avec le fil 2 uniquement. Maintenant, quand t1 et t3 commence sans synchronisé utilisé, la sortie PFB qui suggère que les deux fils 1 et 3 affectant simultanément la valeur de var où pour le fil 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

Utilisation Synchronzied, fil 3 en attente de fil 1 à compléter dans tous les scénarios. Il y a deux verrous acquis, un sur runnable1 partagé par fil 1 et le fil 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

des moyens simples synchronisées pas deux fils peuvent accéder au bloc / procédé simultanément. Quand nous disons un bloc / méthode d'une classe est synchronisée, cela signifie qu'un seul thread peut y accéder à la fois. En interne, le fil qui tente d'y accéder d'abord prendre un verrou sur cet objet et aussi longtemps que ce verrou n'est pas disponible aucun autre thread ne peut accéder à l'une des méthodes / blocs de cette instance synchronisée de la classe.

Remarque un autre thread peut accéder à une méthode du même objet que l'on ne définit pas être synchronisés. Un thread peut libérer le verrou en appelant

Object.wait()

synchronisé est un mot-clé en Java qui est utilisé pour faire qui se passe avant relation dans l'environnement multithreading pour éviter l'incohérence de la mémoire et l'erreur d'interférence de fil.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top