La méthode de synchronisation la plus élémentaire de Java consiste à utiliser le mot-clé synchronisé pour contrôler l'accès simultané d'une méthode. Chaque méthode déclarée avec le mot-clé synchronisé est une section critique. En Java, une seule des sections critiques du même objet est autorisée à être accessible en même temps.
Les méthodes statiques ont des comportements différents. Une méthode statique déclarée avec le mot-clé synchronisé ne peut être accessible que par un thread d'exécution, mais d'autres threads peuvent accéder à la méthode synchronisée non statique de cet objet. Cela doit être très prudent car deux threads peuvent accéder à deux méthodes synchronisées différentes d'un objet en même temps, c'est-à-dire dont l'une est une méthode synchronisée statique et l'autre est une méthode synchronisée non statique. Si les deux méthodes modifient les mêmes données, une erreur incohérente se produira.
La syntaxe du bloc synchronisé est la suivante:
Méthode public void () {synchronisé (expression) {}} Il y a deux utilisations du mot-clé synchronisé. L'un n'est utilisé que dans la définition des méthodes, et l'autre est le bloc synchronisé. Nous pouvons non seulement utiliser synchronisé pour synchroniser une variable d'objet, mais vous pouvez également utiliser SynchronizedL pour synchroniser des méthodes statiques et des méthodes non statiques dans la classe.
Le premier: synchronisation des méthodes non statiques
À partir de la syntaxe liée à Java, nous pouvons savoir que l'utilisation du mot-clé synchronisé pour définir une méthode verrouillera les méthodes statiques et les méthodes non statiques définies par le mot-clé synchroniezd dans la classe, mais c'est un peu difficile à comprendre. Si vous voulez synchroniser des blocs pour réaliser un tel effet, il n'est pas difficile de comprendre pourquoi cet effet est produit. Si vous utilisez synchronisé pour verrouiller toutes les méthodes non statiques synchronisées de la classe, vous n'avez qu'à l'utiliser comme paramètre du bloc synchronisé pour passer dans le bloc synchronisé. Le code est le suivant:
Test de classe publique {public void method1 () {synchronisé (this) {}} public synchronisé void méthode2 () {}} public class test {public void method1 () {synchronisé (this) {}} public synchronisé vide méthode2 () {}} Dans le code ci-dessus, Method1 utilise le bloc synchronisé et la méthode Method2 utilise le mot-clé synchronisé pour définir la méthode. Si vous utilisez la même instance de test, tant qu'une de ces deux méthodes est en cours d'exécution, les autres méthodes seront bloquées car elles n'ont pas obtenu le verrou de synchronisation. En plus de l'utiliser comme paramètre du bloc synchronisé, vous pouvez également utiliser le test. Cela comme paramètre du bloc synchronisé pour obtenir le même effet.
En utilisant des blocs synchronisés dans les classes intérieures, cela ne représente que des classes intérieures et n'a rien à voir avec les classes extérieures (OuterClass). Cependant, les méthodes non statiques dans les classes internes et les méthodes non statiques dans les classes extérieures peuvent également être synchronisées. Si vous ajoutez une méthode méthode3 à la classe intérieure, vous pouvez également vous synchroniser avec les deux méthodes de test, le code est le suivant:
Test de classe publique {class InnerClass {public void method3 () {synchronisé (test.this) {}}} public class test {class innerclass {public void method3 () {synchronisé (test.this) {}}}} La méthode Method3 de Innerclass ci-dessus et les méthodes Method1 et Method2 de test ne peuvent avoir qu'une seule méthode exécutée en même temps.
Que le bloc synchronisé soit exécuté correctement ou que le bloc synchronisé soit sorti en raison d'une exception due à une erreur de programme, le verrouillage de synchronisation détenu par le bloc synchronisé actuel sera automatiquement libéré. Par conséquent, vous n'avez pas à vous soucier du verrou de synchronisation lors de l'utilisation du bloc synchronisé.
2. Synchronisation des méthodes statiques
Étant donné que les instances d'objet ne sont pas nécessairement créées lors de l'appel des méthodes statiques, cela ne peut pas être utilisé pour synchroniser les méthodes statiques, mais doit utiliser des objets de classe pour synchroniser les méthodes statiques. Le code est le suivant:
Test de classe publique {public static void method1 () {synchronisé (test.class) {}} public static synchronisé void méthode2 () {}} classe publique test {public static void méthode1 () {synchronisé (test.class) {}} public static synchronisé méthode2 () {}}Lors de la synchronisation des méthodes statiques, vous pouvez utiliser la classe de champ statique de la classe pour obtenir l'objet de classe. Dans l'exemple ci-dessus, il n'y a qu'une seule exécution de méthode des méthodes Method1 et Method2. En plus d'utiliser le champ de classe, vous pouvez également obtenir l'objet de classe via la méthode getClass () de l'instance. Le code est le suivant:
Test de classe publique {test de test statique public; public test () {test = this; } public static void method1 () {synchronisé (test.getClass ()) {}} Public Class test {public static test test; public test () {test = this; } public static void méthode1 () {synchronisé (test.getClass ()) {}}}
Dans le code ci-dessus, nous obtenons une instance de test via un objet statique public et obtenons un objet de classe via la méthode GetClass de cette instance (notez que toutes les instances d'une classe sont obtenues via la méthode GetClass). Nous pouvons également synchroniser les méthodes statiques de différentes classes à travers la classe, le code est le suivant:
classe publique test1 {public static void method1 () {synchronisé (test.class) {}}} classe publique test1 {public static void method1 () {synchronisé (test.class) {}}}
Remarque: Lorsque des blocs synchronisés sont utilisés pour synchroniser les méthodes, les méthodes non statiques peuvent être synchronisées à travers cela, tandis que les méthodes statiques doivent être synchronisées à l'aide d'objets de classe, mais les méthodes non statiques peuvent également être synchronisées en utilisant la classe. Cependant, cela ne peut pas être utilisé dans des méthodes statiques pour synchroniser les méthodes non statiques. Cela doit être fait attention lors de l'utilisation de blocs synchronisés.
Note
Le mot-clé synchronisé dégradera les performances de l'application et, par conséquent, il ne peut être utilisé que sur des méthodes qui nécessitent de modifier les données partagées dans des scénarios simultanés. Si plusieurs threads accèdent à la même méthode synchronisée, un seul thread peut y accéder et que les autres threads attendront. Si la déclaration de méthode n'utilise pas le mot clé synchronisé, tous les threads peuvent exécuter la méthode en même temps, réduisant ainsi le temps d'exécution total. Si vous êtes connu pour être appelé par plus d'un thread, vous n'avez pas besoin de le déclarer en utilisant le mot-clé synchronisé.
Les méthodes déclarées synchronisées peuvent être appelées récursivement. Lorsqu'un thread accède à la méthode de synchronisation d'un objet, il peut également appeler d'autres méthodes de synchronisation de l'objet, y compris la méthode d'exécution, sans avoir à accéder à nouveau à la méthode.
Nous pouvons protéger l'accès aux blocs de code (plutôt que la méthode entière) via le mot-clé synchronisé. Le mot-clé synchronisé doit être utilisé comme ceci: le reste de la méthode reste en dehors du bloc de code synchronisé pour de meilleures performances. L'accès à la section critique (c'est-à-dire, les blocs de code qui ne peuvent être accessibles qu'en un thread en même temps) ne devraient être aussi courts que possible. Par exemple, dans le fonctionnement de l'obtention du nombre de personnes dans un bâtiment, nous utilisons uniquement le mot-clé synchronisé pour protéger les instructions pour mettre à jour le nombre de personnes et faire en sorte que d'autres opérations n'utilisent pas de données partagées. Lorsque vous utilisez des mots clés synchronisés de cette manière, la référence d'objet doit être utilisée comme paramètre entrant. Un seul thread est autorisé à accéder à ce code synchronisé en même temps. D'une manière générale, nous utilisons ce mot-clé pour désigner l'objet auquel appartient la méthode exécutée:
synchronisé (this) {// Code java}