Maison  >  Article  >  Java  >  Mot clé volatile en Java

Mot clé volatile en Java

王林
王林original
2024-08-30 16:19:44584parcourir

Volatile en Java fonctionne comme si nous voulons que notre objet soit accessible par plusieurs threads simultanément, nous pouvons utiliser ce mot-clé. Ce mot-clé est une autre façon de rendre notre classe, notre code et notre méthode thread-safe, ce qui signifie que plusieurs threads peuvent accéder à la même ressource sans aucun problème. Nous voulons dire que le mot clé violé indique que nous pouvons dire que plusieurs threads manipuleront cette valeur de variable simultanément.

Commencez votre cours de développement de logiciels libres

Développement Web, langages de programmation, tests de logiciels et autres

Quand utilisons-nous le mot-clé volatile en java ?

Si vous souhaitez rendre votre code thread-safe, vous pouvez opter pour le mot-clé viole. En outre, il assure la synchronisation ; dans ce cas, c'est un bon choix.

Toute variable que nous déclarons à l'aide de ce mot-clé n'ira pas dans le cache ; toutes les opérations que nous effectuons, comme la lecture et l'écriture, iront dans la mémoire principale.

class DemoSharedObject
{
static int sharedresources = 10;
}

Ci-dessous un cas qui conduit à une incohérence des données :

Nous avons une classe nommée DemoSharedObject, supposons que plusieurs threads travaillent sur cette classe et vont modifier la valeur des membres de la classe. Ainsi, si plusieurs threads s'exécutent sur les différents processeurs, chacun de ces threads possède ses propres ressources de copie locales. Ainsi, si un thread modifiait la valeur des ressources communes, sa valeur ne serait pas reflétée très rapidement dans la mémoire principale. Mais dans ce cas, nos autres fils de discussion ne connaissent pas la valeur actuelle des ressources partagées, cela entraînera donc un problème d'incohérence des données.

En Java, nous avons deux choses, les instructions de synchronisation et les méthodes de synchronisation.

Méthode de synchronisation

Dans ce cas, nous ajoutons simplement le mot-clé synchronisé à la signature de la méthode.

syntaxe :

public synchronized return_type method_name(){}

Exemple :

public class Demosynchronized {
private int c = 0;
public synchronized void method1() {
c++;
}
public synchronized void method2() {
c--;
}
public synchronized int method3() {
return c;
}
}

Dans l'exemple ci-dessus, nous ne faisons rien d'autre que d'augmenter et de diminuer le compteur, mais nous devons introduire un mot-clé synchronisé avec la méthode afin qu'il n'y ait pas d'incohérence des données et que tous les threads recevront la valeur mise à jour.

Ainsi, lorsque le premier thread effectue son traitement sur la méthode1(), tous les autres threads seront bloqués (suspendus) ; aucun autre thread ne peut accéder au même objet tant que le thread de travail n'a pas déjà acquis le verrou de l'objet. C'est ainsi qu'ils évitent les incohérences des données.

De plus, il y a maintenant plus de choses que chaque fois que le thread termine son opération sur la méthode1(), c'est-à-dire l'exécution complète d'une méthode, il établit donc une relation avec un autre thread afin que les changements dans la valeur ou l'état de l'objet soient visibles. sur d'autres fils également.

Relevé synchronisé

syntaxe :

synchronized(){}

Exemple :

public void demo(String namestr) {
synchronized(this) {
lastName = namestr;
count++;
}
list.add(namestr);
}

Dans l'exemple ci-dessus, nous avons un bloc synchronisé qui va gérer les données pour nous. Comme namestr va être synchronisé par la méthode demo(). Cela signifie les données que nous voulons synchroniser ; nous avons juste besoin de les placer dans ce bloc uniquement.

donc, lorsque nous avons deux threads qui écrivent et lisent sur le même objet, cela signifie que nous avons plusieurs threads qui accèdent au même objet à des fins de lecture et d'écriture, alors nous devrions opter pour le mot-clé viole car il ne nous fournit pas le garantie de blocage des threads à moins et jusqu'à ce que d'autres threads arrêtent leur exécution, donc dans ce cas, nous devrions opter pour la synchronisation car cela nous fournit quelques fonctionnalités supplémentaires par rapport au mot-clé violer comme :

il peut être utilisé avec la méthode ainsi qu'avec le bloc d'instruction, ce qui signifie que nous n'avons pas besoin de synchroniser toute la méthode ; nous pouvons également écrire notre code à l'intérieur du bloc, que nous souhaitons synchroniser.

Lorsque nous lisons ou écrivons la valeur de la variable volatile, ils lisent ou écrivent directement la valeur dans la mémoire principale, ce qui n'est pas une bonne pratique, et cela coûte également cher par rapport au cache. Réfléchissez donc avant d’utiliser des mots-clés volatils ; cela aura un impact direct sur vos performances.

Supposons que nous ayons plusieurs threads qui ne dépendent pas de la réponse de chacun, ce qui signifie que la lecture et l'écriture sont indépendantes l'une de l'autre pour utiliser les mots-clés volatiles dans ce cas. Mais nous avons également un autre cas où il n'est pas approprié d'utiliser le mot-clé volatile qui est expliqué ci-dessous :

Suppose thread has generated the first value of the volatile variable, and this current value will be used further to generate the new volatile variable values; in this case, this volatile keyword is not a good fit to generate the correct result; this condition will lead to a race condition were all thread going to read the same value but generate the new value for them and write the value to main memory and override each other values, so this will leads to the wrong result, or we can say data inconsistency issue, so here volatile keyword is not good enough to avoid this case we have to move to synchronization where we have to types to make our code synchronized, i.e. synchronized method and synchronized statement.

Example

Code:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TvvApplication {
private static final Logger LOGGER = LoggerFactory.getLogger(TvvApplication.class);
private static final Object aclock = new Object();
private static final Object aclock1 = new Object();
private static volatile int MY_INT = 0;
public static void main(String[] args) {
System.out.println("without block");
System.out.println("with block calling static method :: ");
testBlock();
}
static void testBlock1() {
synchronized (aclock1) {
MY_INT = MY_INT + 1;
System.out.println( Thread.currentThread().getName() +"new lock we create and printing voilatile value using block for block one:: "+ MY_INT);
}
}
static void testBlock() {
synchronized (aclock) {
MY_INT = MY_INT + 1;
System.out.println( Thread.currentThread().getName() +"new lock we create and printing voilatile value using block for block two:: "+ MY_INT);
}
}
}

Output :

<img src="https://img.php.cn/upload/article/000/000/000/172500598784733.png" alt="Mot clé volatile en Java" >

Conclusion

So this can provide thread safety when data does not depend on each other; if data depends, we should go for synchronization.

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!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Article précédent:Composants AWT en JavaArticle suivant:Composants AWT en Java