Je pense que les lecteurs qui comprennent le multithreading Java connaîtront clairement son rôle. Le mot-clé volatile est utilisé pour déclarer des variables de type simple, telles que int, float, boolean et d'autres types de données. Si ces types de données simples sont déclarés volatils, les opérations sur ces types de données deviennent atomiques. Mais cela présente certaines limites. Par exemple, n dans l’exemple suivant n’est pas atomique :
Copiez le code comme suit :
mythread du paquet ;
la classe publique JoinThread étend Thread
{
public statique volatile int n = 0 ;
exécution publique vide()
{
pour (int i = 0; i < 10; i++)
essayer
{
n = n + 1 ;
sleep(3); // Afin de rendre les résultats en cours d'exécution plus aléatoires, retardez 3 millisecondes
}
attraper (exception e)
{
}
}
public static void main (String[] args) lève une exception
{
Fils de discussion[] = nouveau fil[100] ;
pour (int i = 0; i < threads.length; i++)
// Crée 100 fils de discussion
threads[i] = new JoinThread();
pour (int i = 0; i < threads.length; i++)
//Exécute les 100 threads qui viennent d'être créés
fils[i].start();
pour (int i = 0; i < threads.length; i++)
//Continuer après que les 100 threads aient été exécutés
fils de discussion[i].join();
System.out.println("n=" + JoinThread.n);
}
}
Si l'opération sur n est atomique, le résultat final doit être n=1000. Cependant, lors de l'exécution de l'indicatif régional ci-dessus, la sortie n est souvent inférieure à 1000, ce qui montre que n=n+1 n'est pas une opération de niveau atomique. . La raison en est que pour une variable simple déclarée volatile, si la valeur actuelle est liée à la valeur précédente de la variable, alors le mot-clé volatile n'a aucun effet, ce qui signifie que les expressions suivantes ne sont pas des opérations atomiques :
Copiez le code comme suit :
n = n + 1 ;
n++;
Si vous souhaitez faire de cette situation une opération atomique, vous devez utiliser le mot-clé synchronisé. Le code ci-dessus peut être modifié sous la forme suivante :
Copiez le code comme suit :
mythread du paquet ;
la classe publique JoinThread étend Thread
{
public statique int n = 0 ;
public statique synchronisé void inc()
{
n++;
}
exécution publique vide()
{
pour (int i = 0; i < 10; i++)
essayer
{
inc(); // n = n + 1 remplacé par inc();
sleep(3); // Afin de rendre les résultats en cours d'exécution plus aléatoires, retardez 3 millisecondes
}
attraper (exception e)
{
}
}
public static void main (String[] args) lève une exception
{
Fils de discussion[] = nouveau fil[100] ;
pour (int i = 0; i < threads.length; i++)
// Crée 100 fils de discussion
threads[i] = new JoinThread();
pour (int i = 0; i < threads.length; i++)
//Exécute les 100 threads qui viennent d'être créés
fils[i].start();
pour (int i = 0; i < threads.length; i++)
//Continuer après que les 100 threads aient été exécutés
fils de discussion[i].join();
System.out.println("n=" + JoinThread.n);
}
}
Le code ci-dessus change n=n+1 en inc(), où la méthode inc utilise le mot-clé synchronisé pour la synchronisation des méthodes. Soyez donc prudent lorsque vous utilisez le mot-clé volatile. Cela ne signifie pas que les variables de type simple sont modifiées avec volatile. Toutes les opérations sur cette variable sont les opérations d'origine lorsque la valeur de la variable est déterminée par sa précédente, comme n=. n+1 , n++, etc., le mot-clé volatile ne sera pas valide. L'opération sur la variable est au niveau atomique uniquement lorsque la valeur de la variable n'a rien à voir avec sa valeur précédente. Par exemple, n = m + 1, this. est le niveau d'origine. Par conséquent, vous devez être prudent lorsque vous utilisez des clés volatiles. Si vous n'êtes pas sûr, vous pouvez utiliser synchronisé au lieu de volatile.