Quelle est la différence entre volatile et synchroniser ?
Différences : 1. La volatilité ne provoquera pas de blocage du fil ; la synchronisation peut provoquer un blocage du fil. 2. Volatile garantit la visibilité des données, mais ne peut pas garantir l'atomicité, tandis que la synchronisation peut garantir l'atomicité et indirectement garantir la visibilité.
Visibilité
Visibilité : Une paire de threads Après une variable partagée est modifiée, les autres threads peuvent immédiatement voir (percevoir) la modification (changement) de la variable.
Le modèle de mémoire Java synchronise les valeurs modifiées des variables dans la mémoire de travail avec la mémoire principale et actualise les dernières valeurs de la mémoire principale vers la mémoire de travail avant de lire les variables. sur la mémoire principale pour obtenir de la visibilité.
Atomicité (Atomicité)
Atomicité : Une opération ne peut pas être interrompue, soit elle est entièrement exécutée, soit elle ne l'est pas exécuté.
Ce que garantit le modèle de mémoire Java, c'est que toutes les opérations au sein du même thread se font de haut en bas. Cependant, lorsque plusieurs threads s'exécutent en parallèle, l'ordre de leurs opérations ne peut pas être garanti.
Ordre
Ordre : Observez dans ce fil, les opérations sont toutes dans l'ordre si dans un Lorsque vous observez un autre fil dans ; un fil, toutes les opérations sont dans le désordre.
Ce que garantit le modèle de mémoire Java, c'est que toutes les opérations au sein du même thread se font de haut en bas. Cependant, lorsque plusieurs threads s'exécutent en parallèle, l'ordre de leurs opérations ne peut pas être garanti.
Lorsque l'ordinateur exécute un programme, afin d'améliorer les performances, le compilateur et le processeur réorganisent souvent les instructions , qui sont généralement divisées en trois types suivants
Unique -environnement threadé Il garantit que le résultat final de l'exécution du programme est cohérent avec le résultat de l'exécution du code
Le processeur doit prendre en compte les dépendances de données entre les instructions lors de la réorganisation
Dans un environnement multithread Dans l'environnement, les threads s'exécutent alternativement. En raison de l'existence d'un réarrangement d'optimisation du compilateur, il n'est pas certain que les variables utilisées dans les deux threads puissent assurer la cohérence des variables utilisées, et les résultats sont imprévisibles
Faites ce que vous pouvez faire dans le examen d'abord, et faites ce que vous ne pouvez pas faire plus tard.
public void mySort(){ int x = 11; //1 int y = 12; //2 x= x+5; // 3 y = x*x;//4
Ordre possible 1234 2134 1324, attribut 4 impossible avant 1 et 3, à cause de la dépendance des données.
volatile interdit la réorganisation des instructions.
public class ReSortSeqDemo { int a = 0; boolean flag = false; public void method01() { a = 1; // flag = true; // ----线程切换---- flag = true; // a = 1; } public void method02() { if (flag) { a = a + 3; System.out.println("a = " + a); } } }
Si deux threads sont exécutés en même temps, la méthode01 et la méthode02 sont réorganisées si le thread 1 exécute la méthode01, puis le thread commuté 2 exécute la méthode02, il y aura des résultats différents.
Désactiver la réorganisation des instructions
volatile réalise l'optimisation de la désactivation de la réorganisation des instructions, évitant ainsi le phénomène de désordre du programme dans un environnement multithread
Comprenez d'abord un concept. La barrière mémoire, également connue sous le nom de barrière mémoire, est une instruction CPU. Elle a deux fonctions :
Garantir l'ordre d'exécution d'opérations spécifiques
Assurer qu'une certaine mémoire. visibilité de certaines variables (utilisez cette fonctionnalité pour obtenir une visibilité de la mémoire volatile)
Étant donné que le compilateur et chaque processeur peuvent effectuer une optimisation de la réorganisation des instructions, si une barrière de mémoire est insérée entre les instructions, elle le dira au compilateur et au processeur, aucune instruction ne peut réorganiser cette instruction Memory Barrier, ce qui signifie que la réorganisation de l'optimisation avant et après la barrière mémoire est interdite par l'insertion d'une barrière mémoire. Une autre fonction de la barrière mémoire est de forcer le vidage de diverses données du cache du processeur, afin que n'importe quel thread du processeur puisse lire la dernière version de ces données.
Ce qui suit est un diagramme schématique de la séquence d'instructions générée après l'insertion d'une écriture volatile dans la barrière mémoire selon la stratégie conservatrice :
Ce qui suit est la séquence d'instructions générée après une lecture volatile est inséré dans la barrière mémoire sous la stratégie conservatrice Schéma schématique :
Garantie de sécurité des threads
Le délai de synchronisation entre la mémoire de travail et la mémoire principale provoquent des problèmes de visibilité
Peuvent être résolus à l'aide de mots-clés synchronisés ou volatiles, qui peuvent utiliser des variables modifiées par un thread pour être immédiatement visibles par les autres threads
Pour les problèmes de visibilité et les problèmes d'ordre causés par le réarrangement des instructions
peut être résolu en utilisant le mot clé volatile, car une autre fonction de volatile est d'interdire l'optimisation de la réorganisation des instructions
volatile
le variable qu'elle modifieNe pas en conserver de copie, accéder directement à la mémoire principale .
Dans le modèle de mémoire Java, il y a mémoire principale, et chaque thread possède également sa propre mémoire (comme des registres). Pour des raisons de performances, un thread conserve une copie des variables auxquelles il accède dans sa propre mémoire. De cette façon, il y aura des situations où la valeur de la même variable dans la mémoire d'un thread peut être incohérente avec la valeur dans la mémoire d'un autre thread ou avec la valeur dans la mémoire principale à un certain moment. Déclarer une variable comme volatile signifie que la variable peut être modifiée par d'autres threads à tout moment, elle ne peut donc pas être mise en cache dans la mémoire des threads.
Scénarios d'utilisation
Vous ne pouvez utiliser des variables volatiles pour remplacer les verrous que dans des situations limitées. Pour que les variables volatiles offrent une sécurité idéale des threads, les deux conditions suivantes doivent être remplies en même temps :
1) L'opération d'écriture dans la variable ne dépend pas de la valeur actuelle.
2) La variable n'est pas incluse dans un invariant avec d'autres variables.
volatile est le plus approprié pour les situations où un thread écrit et plusieurs threads lisent.
Si plusieurs threads écrivent simultanément, vous devez toujours utiliser des verrous, des conteneurs thread-safe ou des variables atomiques à la place.
synchronisé
Lorsqu'il est utilisé pour modifier une méthode ou un bloc de code , il peut assurer Au plus un thread peut exécuter ce code en même temps .
- Lorsque deux threads simultanés accèdent au bloc de code de synchronisation synchronisé (this) dans le même objet objet, un seul thread peut être exécuté à la fois. Un autre thread doit attendre que le thread actuel ait fini d'exécuter ce bloc de code avant de pouvoir exécuter ce bloc de code.
- Cependant, lorsqu'un thread accède à un bloc de code synchronisé (this) d'un objet, un autre thread peut toujours accéder au bloc de code synchronisé non synchronisé (this) dans l'objet.
- Ce qui est particulièrement critique est que lorsqu'un thread accède à un bloc de code synchronisé (this) d'un objet, l'accès des autres threads à tous les autres blocs de code synchronisés (this) dans l'objet sera bloqué.
- Lorsqu'un thread accède à un bloc de code synchronisé d'objet, il obtient le verrou d'objet de cet objet. En conséquence, l'accès des autres threads à toutes les parties de code synchronisées de l'objet objet est temporairement bloqué .
Ressources partagées et objets d'ajout, de suppression et de modification.
Lock
À partir de jdk 5.0, Java fournit un mécanisme de synchronisation de threads plus puissant - la synchronisation est obtenue en définissant explicitement les objets de verrouillage de synchronisation, et les verrous de synchronisation sont L'objet de verrouillage utilisé agit comme.
L'interface java.util.concurrent.Locks.Lock est un outil permettant de contrôler l'accès de plusieurs threads aux ressources partagées. Les verrous fournissent un accès exclusif aux ressources partagées. Un seul thread à la fois peut verrouiller l'objet Lock. Le thread doit obtenir l'objet Lock avant de commencer à accéder aux ressources partagées.
La classe ReentrantLock implémente Lock, qui a la même concurrence et la même sémantique de mémoire que synchronisée. Pour réaliser le contrôle de la sécurité des threads, ReentrantLock est plus couramment utilisé et peut afficher les verrous et les libérer.
Différence
volatile et synchronisée
volatile est un modificateur de variable, tandis que synchronisé agit sur un morceau de code ou une méthode .
volatile synchronise simplement la valeur d'une variable entre la mémoire du thread et la mémoire "principale" ; tandis que synchronisé synchronise la valeur de toutes les variables en verrouillant et déverrouillant un moniteur, évidemment synchronisé vaut mieux que volatile consomme plus de ressources.
volatile ne provoquera pas de blocage des threads ; synchronisé peut provoquer un blocage des threads.
volatile garantit la visibilité des données, mais ne peut pas garantir l'atomicité tandis que synchronisé peut garantir l'atomicité et indirectement garantir la visibilité, car il le fera. synchroniser les données dans la mémoire privée et la mémoire publique.
Les variables marquées comme volatiles ne seront pas optimisées par le compilateur ; les variables marquées comme synchronisées peuvent être optimisées par le compilateur.
La sécurité des threads comprend deux aspects : l'atomicité et la visibilité. Le mécanisme de synchronisation de Java se concentre sur ces deux aspects pour garantir la sécurité des threads.
Le mot-clé volatile est principalement utilisé lorsque plusieurs threads peuvent détecter que des variables d'instance ont été modifiées et peuvent obtenir la dernière valeur. Autrement dit, lorsque plusieurs threads lisent des variables partagées, ils peuvent obtenir la dernière valeur.
Le mot clé volatile invite le thread à lire à chaque fois les variables de la mémoire partagée au lieu de lire depuis la mémoire privée, assurant ainsi la visibilité des données synchronisées. Mais attention : si vous modifiez les données dans la variable d'instance
Par exemple : i++, c'est-à-dire i=i+1, alors une telle opération n'est pas réellement une opération atomique, c'est-à-dire qu'elle n'est pas thread-safe. Les étapes de fonctionnement de l'expression i++ se décomposent comme suit :
1) Récupérer la valeur de i en mémoire.
2) Calculez la valeur de i;
3) Écrivez la valeur de i en mémoire.
Si un autre thread modifie également la valeur de i lors du calcul de la valeur à l'étape 2, les données de lecture sales apparaîtront dans le nom à ce moment-là. La solution consiste à utiliser le mot-clé synchronisé. So volatile lui-même ne gère pas l'atomicité des données, mais force la lecture et l'écriture des données à affecter la mémoire principale en temps opportun.
synchronisé et verrouillé
Le verrouillage est un verrouillage d'affichage (ouverture et fermeture manuelles, n'oubliez pas d'éteindre le verrouillage), synchronisé est un implicite Verrouillage, hors de portée Libérez automatiquement le verrou.
Le verrouillage verrouille uniquement les blocs de code, synchronisé peut agir sur les blocs de code et les méthodes.
Grâce à Lock, la JVM passe moins de temps à planifier les threads et fonctionne mieux. Et a une meilleure évolutivité (offrant plus de sous-classes).
Séquence d'utilisation : Verrouiller-> bloc de code synchronisé (est entré dans le corps de la méthode et a alloué les ressources correspondantes) ->
Pour plus de connaissances liées à la programmation, veuillez visiter : Cours d'apprentissage en programmation ! !
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Outils d'IA chauds

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool
Images de déshabillage gratuites

Clothoff.io
Dissolvant de vêtements AI

AI Hentai Generator
Générez AI Hentai gratuitement.

Article chaud

Outils chauds

Bloc-notes++7.3.1
Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Guide du nombre parfait en Java. Nous discutons ici de la définition, comment vérifier le nombre parfait en Java ?, des exemples d'implémentation de code.

Guide du générateur de nombres aléatoires en Java. Nous discutons ici des fonctions en Java avec des exemples et de deux générateurs différents avec d'autres exemples.

Guide de Weka en Java. Nous discutons ici de l'introduction, de la façon d'utiliser Weka Java, du type de plate-forme et des avantages avec des exemples.

Guide du nombre de Smith en Java. Nous discutons ici de la définition, comment vérifier le numéro Smith en Java ? exemple avec implémentation de code.

Dans cet article, nous avons conservé les questions d'entretien Java Spring les plus posées avec leurs réponses détaillées. Pour que vous puissiez réussir l'interview.

Java 8 présente l'API Stream, fournissant un moyen puissant et expressif de traiter les collections de données. Cependant, une question courante lors de l'utilisation du flux est: comment se casser ou revenir d'une opération FOREAK? Les boucles traditionnelles permettent une interruption ou un retour précoce, mais la méthode Foreach de Stream ne prend pas directement en charge cette méthode. Cet article expliquera les raisons et explorera des méthodes alternatives pour la mise en œuvre de terminaison prématurée dans les systèmes de traitement de flux. Lire plus approfondie: Améliorations de l'API Java Stream Comprendre le flux Forach La méthode foreach est une opération terminale qui effectue une opération sur chaque élément du flux. Son intention de conception est

Guide de TimeStamp to Date en Java. Ici, nous discutons également de l'introduction et de la façon de convertir l'horodatage en date en Java avec des exemples.

Java est un langage de programmation populaire qui peut être appris aussi bien par les développeurs débutants que par les développeurs expérimentés. Ce didacticiel commence par les concepts de base et progresse vers des sujets avancés. Après avoir installé le kit de développement Java, vous pouvez vous entraîner à la programmation en créant un simple programme « Hello, World ! ». Une fois que vous avez compris le code, utilisez l'invite de commande pour compiler et exécuter le programme, et « Hello, World ! » s'affichera sur la console. L'apprentissage de Java commence votre parcours de programmation et, à mesure que votre maîtrise s'approfondit, vous pouvez créer des applications plus complexes.
