Copiez le code comme suit :
exécution vide synchronisée publique ()
{
}
Comme le montre le code ci-dessus, tant que le mot-clé synchronisé est ajouté entre void et public, la méthode run peut être synchronisée, c'est-à-dire que pour l'instance d'objet de la même classe Java, la méthode run ne peut être synchronisée. appelé par un thread en même temps et ne peut être appelé par d'autres threads qu'après l'exécution de l'exécution en cours. Même si le thread actuel exécute la méthode rendement dans la méthode run, il ne s'arrête que pendant un moment. Étant donné que les autres threads ne peuvent pas exécuter la méthode run, le thread actuel continuera finalement son exécution. Jetez d'abord un œil au code suivant :
Le mot-clé synchronisé n'est lié qu'à une seule instance d'objet
Copiez le code comme suit :
Test de classe
{
méthode vide synchronisée publique ()
{
}
}
la classe publique Sync implémente Runnable
{
test de test privé ;
exécution publique vide()
{
test.method();
}
synchronisation publique (Test test)
{
this.test = test;
}
public static void main (String[] args) lève une exception
{
Test test1 = nouveau Test();
Test test2 = nouveau Test();
Sync sync1 = nouvelle Sync(test1);
Sync sync2 = nouvelle Sync(test2);
new Thread(sync1).start();
new Thread(sync2).start();
}
}
Les méthodes de la classe Test sont synchrones. Mais le code ci-dessus crée deux instances de la classe Test, donc les méthodes test1 et test2 sont exécutées séparément. Pour synchroniser les méthodes, vous devez passer une instance de la même classe Test dans son constructeur lors de la création d'une instance de la classe Sync, comme indiqué dans le code suivant :
Sync sync1 = nouvelle Sync(test1);
Non seulement vous pouvez utiliser synchronisé pour synchroniser des méthodes non statiques, mais vous pouvez également utiliser synchronisé pour synchroniser des méthodes statiques. Par exemple, la méthode méthode peut être définie comme suit :
Copiez le code comme suit :
Test de classe
{
méthode vide synchronisée statique publique() { }
}
Créez une instance d'objet de la classe Test comme suit :
Test test = nouveau Test();
Pour les méthodes statiques, tant que le mot-clé synchronisé est ajouté, la méthode est synchronisée. Que vous utilisiez test.method() ou Test.method() pour appeler la méthode, la méthode est synchronisée et n'existe pas. instances de méthodes non statiques.
Parmi les 23 modèles de conception, le mode Singleton est également non sécurisé pour les threads s'il est conçu selon les méthodes traditionnelles. Le code suivant est un mode Singleton non sécurisé pour les threads.
Copiez le code comme suit :
test de paquet ;
// Mode Singleton thread-safe
classe Singleton
{
échantillon Singleton statique privé ;
Singleton privé()
{
}
public statique Singleton getInstance()
{
si (échantillon == null)
{
Thread.yield(); // Afin d'amplifier l'insécurité des threads du mode Singleton
échantillon = nouveau Singleton();
}
retourner un échantillon ;
}
}
la classe publique MyThread étend Thread
{
exécution publique vide()
{
Singleton singleton = Singleton.getInstance();
System.out.println(singleton.hashCode());
}
public static void main (String[] arguments)
{
Fils de discussion[] = nouveau fil[5] ;
pour (int i = 0; i < threads.length; i++)
fils[i] = nouveau MonThread();
pour (int i = 0; i < threads.length; i++)
fils[i].start();
}
}
La méthode rendement est appelée dans le code ci-dessus pour faire apparaître la non-sécurité des threads du mode singleton. Si cette ligne est supprimée, l'implémentation ci-dessus est toujours non sécurisée pour les threads, mais la possibilité d'occurrence est beaucoup plus petite.
Les résultats de l'exécution du programme sont les suivants :
Copiez le code comme suit :
25358555
26399554
7051261
29855319
5383406
Les résultats d'exécution ci-dessus peuvent être différents selon les environnements d'exécution, mais généralement les cinq lignes de sortie ne seront pas exactement les mêmes. Comme le montre cette sortie, il existe cinq instances d'objet obtenues via la méthode getInstance, et non une comme nous l'espérions. En effet, lorsqu'un thread exécute Thread.yield(), il transmet les ressources CPU à un autre thread. Étant donné que l'instruction permettant de créer une instance d'objet Singleton n'est pas exécutée lors du basculement entre les threads, ces threads passent tous le jugement if, donc cinq instances d'objet seront créées (quatre peuvent être créées ou trois instances d'objet, selon le nombre de threads réussis). le jugement if avant de créer l'objet Singleton, le résultat peut être différent à chaque exécution).
Pour rendre le mode singleton ci-dessus thread-safe, ajoutez simplement le mot-clé synchronisé à getInstance. Le code est le suivant :
public statique synchronisé Singleton getInstance() { }
Bien entendu, il existe un moyen plus simple, qui consiste à créer un objet Singleton lors de la définition de la variable Singleton. Le code est le suivant :
échantillon Singleton final statique privé = new Singleton ();
Ensuite, renvoyez simplement l’échantillon directement dans la méthode getInstance. Bien que cette méthode soit simple, elle n'est pas flexible pour créer un objet Singleton dans la méthode getInstance. Les lecteurs peuvent choisir d'utiliser différentes méthodes pour implémenter le modèle singleton en fonction de besoins spécifiques.
Il y a quatre points à noter lors de l'utilisation du mot-clé synchronisé :
1. Le mot-clé synchronisé ne peut pas être hérité.
Bien que vous puissiez utiliser synchronisé pour définir des méthodes, synchronisé ne fait pas partie de la définition de la méthode, le mot clé synchronisé ne peut donc pas être hérité. Si une méthode de la classe parent utilise le mot-clé synchronisé et remplace cette méthode dans la sous-classe, la méthode de la sous-classe n'est pas synchronisée par défaut et doit être explicitement spécifiée dans la sous-classe. Ajoutez simplement le mot-clé synchronisé à la méthode. Bien entendu, vous pouvez également appeler la méthode correspondante dans la classe parent dans la méthode de la sous-classe. De cette façon, bien que la méthode de la sous-classe ne soit pas synchrone, la sous-classe appelle la méthode de synchronisation de la classe parent. la sous-classe est équivalente à la synchronisation. Des exemples de codes pour ces deux méthodes sont les suivants :
Ajoutez le mot-clé synchronisé à la méthode de sous-classe
Copiez le code comme suit :
Parent de classe
{
méthode vide synchronisée publique() { }
}
classe L'enfant étend le parent
{
méthode vide synchronisée publique() { }
}
Appelez la méthode synchronisée de la classe parent dans la méthode de la sous-classe
Copiez le code comme suit :
Parent de classe
{
méthode vide synchronisée publique() { }
}
classe L'enfant étend le parent
{
public void method() { super.method();
}
2. Le mot-clé synchronisé ne peut pas être utilisé lors de la définition des méthodes d'interface.
3. Le constructeur ne peut pas utiliser le mot-clé synchronisé, mais peut utiliser le bloc synchronisé dont il sera question dans la section suivante pour la synchronisation.
4. Synchronisé peut être placé librement.
Dans les exemples précédents, le mot-clé synchronisé est placé devant le type de retour de la méthode. Mais ce n’est pas le seul endroit où la synchronisation peut être placée. Dans les méthodes non statiques, synchronisé peut également être placé au début de la définition de la méthode. Dans les méthodes statiques, synchronisé peut être placé devant statique. Le code est le suivant :
Copiez le code comme suit :
méthode vide synchronisée publique ();
méthode public void synchronisée ();
méthode vide synchronisée statique publique ();
méthode de vide statique synchronisée publique ();
méthode de vide statique publique synchronisée ();
Mais veuillez noter que synchronisé ne peut pas être placé après le type de retour de la méthode. Par exemple, le code suivant est erroné :
Copiez le code comme suit :
méthode synchronisée public void ();
méthode synchronisée public static void ();
Le mot-clé synchronisé ne peut être utilisé que pour synchroniser des méthodes, pas des variables de classe. Le code suivant est également erroné.
Copiez le code comme suit :
public synchronisé int n = 0 ;
public statique synchronisé int n = 0 ;
Bien que l'utilisation de la méthode de synchronisation par mot-clé synchronisé soit la méthode de synchronisation la plus sûre, une utilisation intensive du mot-clé synchronisé entraînera une consommation inutile de ressources et une perte de performances. Bien qu'à première vue, il semble que synchronisé verrouille une méthode, en fait synchronisé verrouille une classe. En d’autres termes, si synchronisé est utilisé lors de la définition des méthodes non statiques méthode1 et méthode2, méthode2 ne peut pas être exécutée avant l’exécution de méthode1. La situation est similaire pour les méthodes statiques et non statiques. Mais les méthodes statiques et non statiques ne s’influencent pas. Jetez un œil au code suivant :
Copiez le code comme suit :
test de paquet ;
la classe publique MyThread1 étend Thread
{
public String nom_méthode ;
méthode publique static void (String s)
{
System.out.println(s);
tandis que (vrai)
}
méthode vide synchronisée publique1()
{
method("méthode méthode1 non statique");
}
méthode vide synchronisée publique2()
{
method("méthode méthode2 non statique");
}
méthode vide synchronisée statique publique3()
{
méthode("méthode statique3");
}
méthode vide synchronisée statique publique4()
{
méthode("méthode statique4");
}
exécution publique vide()
{
essayer
{
getClass().getMethod(methodName).invoke(this);
}
attraper (exception e)
{
}
}
public static void main (String[] args) lève une exception
{
MonThread1 monThread1 = new MyThread1();
pour (int i = 1; i <= 4; i++)
{
monThread1.methodName = "méthode" + String.valueOf(i);
new Thread(monThread1).start();
dormir (100);
}
}
}
Les résultats en cours d'exécution sont les suivants :
Copiez le code comme suit :
Méthode non statique1 méthode
Méthode statique3 méthode
Comme le montrent les résultats d'exécution ci-dessus, les méthodes 2 et 4 ne peuvent pas être exécutées avant que les méthodes 1 et 3 ne soient terminées. Par conséquent, nous pouvons conclure que si vous utilisez le mot-clé synchronisé pour définir une méthode non statique dans une classe, cela affectera toutes les méthodes non statiques définies à l'aide du mot-clé synchronisé dans cette classe. Si une méthode statique est définie, elle affectera toutes les méthodes statiques définies à l'aide du mot-clé synchronisé dans la classe. C'est un peu comme un verrouillage de table dans une table de données. Lorsqu'un enregistrement est modifié, le système verrouille la table entière. Par conséquent, une utilisation intensive de cette méthode de synchronisation réduira considérablement les performances du programme.