J'ai des questions concernant l'utilisation et la signification du synchronized
mot clé.
- Quelle est la signification du
synchronized
mot-clé? - Quand les méthodes devraient-elles être
synchronized
? - Qu'est-ce que cela signifie par programmation et logique?
java
multithreading
keyword
synchronized
Johanna
la source
la source
Réponses:
Le
synchronized
mot-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: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 lesynchronized
mot - clé, votre thread 1 peut ne pas voir le changement de thread 2foo
ou 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.
la source
Eh bien, je pense que nous en avions assez d'explications théoriques, alors considérez ce code
Remarque:
synchronized
bloque 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. Sanssynchronized
tous 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é
Sortie sans synchronisé
la source
synchronized
, mais la cohérence de la mémoire est ignorée.Le
synchronized
mot-clé empêche l'accès simultané à un bloc de code ou d'objet par plusieurs threads. Toutes les méthodes deHashtable
sontsynchronized
, donc un seul thread peut exécuter l'une d'entre elles à la fois.Lorsque vous utilisez des
synchronized
constructions non similairesHashMap
, vous devez créer des fonctionnalités de sécurité des threads dans votre code pour éviter les erreurs de cohérence.la source
synchronized
signifie que dans un environnement multi-thread, un objet ayant dessynchronized
méthodes / blocs ne laisse pas deux threads accédersynchronized
simultané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
synchronized
blocs n'offrent aucun avantage.la source
Le
synchronized
mot 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:
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.
la source
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
synchronized
mot - clé prend unObject
paramè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
synchronized
d'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 étantthis
(pour les méthodes par exemple) etClassInQuestion.getClass()
(pour les méthodes de classe) .- La méthode d'instance est une méthode qui n'a pas de
static
mot - clé.- La méthode de classe est une méthode qui a un
static
mot-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.
la source
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.
la source
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 .
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.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:
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.
La synchronisation des méthodes a deux effets :
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.
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?
la source
Synchronized normal method
équivalent àSynchronized statement
(utiliser ceci)Synchronized static method
équivalent àSynchronized statement
(classe d'utilisation)Instruction synchronisée (à l'aide d'une variable)
Pour
synchronized
, nous avons les deuxSynchronized Methods
etSynchronized Statements
. Cependant,Synchronized Methods
est similaire àSynchronized Statements
donc nous avons juste besoin de comprendreSynchronized Statements
.=> Fondamentalement, nous aurons
Voici 2 pense que aider à comprendre
synchronized
intrinsic lock
associé.synchronized statement
, il acquiert automatiquement leintrinsic lock
pour cetsynchronized statement's
objet et le libère lorsque la méthode revient. Tant qu'un thread possède unintrinsic lock
, aucun autre thread ne peut acquérir le même verrou => thread-safe.=> Quand a
thread A
invoquesynchronized(this){// code 1}
=> tout le code de bloc (à l'intérieur de la classe) où havesynchronized(this)
et toutsynchronized normal method
(à l'intérieur de la classe) est verrouillé car SAME se verrouille. Il s'exécutera aprèsthread A
déverrouillage ("// code 1" terminé).Ce comportement est similaire à
synchronized(a variable){// code 1}
ousynchronized(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 statements
car 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'utilisationsynchronized(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 method
pour rendre le code plus court et facile à comprendreRemarque
(ce n'est pas pertinent pour beaucoup
synchronized
, c'est la différence entre objet et classe ou non-statique et statique).synchronized
ou la méthode normale ousynchronized(this)
ousynchronized(non-static variable)
il synchronisera la base sur chaque instance d'objet.synchronized
ou une méthode statique ousynchronized(class)
ousynchronized(static variable)
il synchronisera la base sur la classeRé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
la source
Voici une explication des Java Tutorials .
Considérez le code suivant:
la source
À 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).
la source
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":
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.
la source
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:
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.
À 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.
la source
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
la source
synchronized
block en Java est un moniteur en multithreading.synchronized
bloc avec le même objet / classe peut être exécuté par un seul thread, tous les autres attendent. Cela peut aider dans larace condition
situation où plusieurs threads essaient de mettre à jour la même variable (la première étape utilisevolatile
About )Java 5
étendusynchronized
en soutenanthappens-before
[À propos]La prochaine étape est
java.util.concurrent
volatile vs synchronisé
la source
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.
la source