Synchronisation en Java
Qu’est ce qu' Synchronisation en Java?
In Java, la synchronisation fait référence à la capacité de contrôler l'accès de plusieurs threads à n'importe quelle ressource partagée. C'est une option idéale lorsque nous souhaitons autoriser un seul thread à accéder à la ressource partagée.
Cette approche d'exécution est généralement appelée programmation « asynchrone ». Il existe également des threads sur ces processeurs, qui sont des processus légers capables d'exécuter des instructions simultanément.
Types d' Synchronisation
Il existe deux types de méthodes de synchronisation dans Java:
1) Synchronisation des processus
2) Synchronisation des threads.
Étudions Thread et Synchronisation des processus en détail.
Synchronisation des processus : Il gère la synchronisation entre les programmes. Par exemple, des programmes tels que `Microsoft Word` et `Acrobat reader` s'exécutent en tant que processus individuels.
Synchronisation des threads : L'exécution simultanée de la ressource critique par deux ou plusieurs threads est appelée Thread. Synchronisation. Vous pouvez être regroupés davantage pour une communication mutuellement exclusive et inter-thread.
Qu'est-ce que le verrouillage Java?
Verrouiller Java est construit autour d’une entité interne appelée moniteur ou verrou. Tous les objets sont associés à un verrou. Ainsi, le thread qui a besoin d'un accès cohérent aux champs d'un objet doit acquérir le verrou de l'objet avant d'y accéder, et il libère le verrou lorsque le travail est terminé. Cela garantit qu'un seul thread accède aux données partagées à la fois.
Programme multithread avec synchronisation
Un programme multithread est une méthode ou un bloc protégé des interférences d'autres threads partageant la même ressource indiquée à l'aide du mot-clé « synchronized ».
Utiliser la méthode synchronisée
Toute méthode déclarée comme synchronisée est appelée méthode synchronisée. Il est également utilisé pour verrouiller un objet pour toute ressource partagée. Ainsi, lorsqu'un thread invoque une méthode synchronisée. Il prend automatiquement possession du verrou de cet objet et le libère lorsqu'il a terminé sa tâche.
Remarque : Le mot-clé synchronisé ne peut pas fonctionner avec les classes et les variables. Seules les méthodes et les blocs peuvent être utilisés avec le mot-clé.
Pourquoi utiliser le SyncMéthode hronisée ?
- Il est utilisé pour verrouiller un objet pour toutes les ressources partagées.
- L'objet obtient le verrou chaque fois que la méthode synchronisée est appelée.
- Le verrou ne se libère que lorsque le fil a terminé sa fonction
syntaxe:
Acess_modifiers synchronized return_type method_name (Method_Parameters) { }
class MathService { synchronized void getSumOfArray(int[] numbers) { int sum = 0; for (int number : numbers) { System.out.println(Thread.currentThread() .getName() + " adds " + sum + " to " + number + " to get -> " + (sum += number)); try { Thread.sleep(500); } catch (InterruptedException e) { throw new RuntimeException(e); } } } } public class Synchronization { public static void main(String[] args) { MathService mathService = new MathService(); Thread threadOne = new Thread(() -> mathService.getSumOfArray(new int[]{10, 11, 12})); Thread threadTwo = new Thread(() -> mathService.getSumOfArray(new int[]{20, 21, 22})); threadOne.start(); threadTwo.start(); } }
Explication du code :
Exécutez cet exemple et observez que le thread « 0 » obtient d'abord le verrou de l'objet « mathService » et utilise ce verrou exclusivement jusqu'à ce qu'il ait terminé son exécution. Les threads « 0 » et « 1 » ne sont pas entrelacés dans ce code. Le résultat est comme indiqué ci-dessous.
Sortie :
Thread-0 adds 0 to 10 to get -> 10 Thread-0 adds 10 to 11 to get -> 21 Thread-0 adds 21 to 12 to get -> 33 Thread-1 adds 0 to 20 to get -> 20 Thread-1 adds 20 to 21 to get -> 41 Thread-1 adds 41 to 22 to get -> 63
Utiliser un bloc synchronisé
Supposons que vous ne souhaitiez pas synchroniser l'intégralité de la méthode. Au lieu de cela, vous souhaitez synchroniser quelques lignes de code. À ce moment-là, SyncLe bloc horronisé a aidé à synchroniser ce qui a été sélectionné Java code. SyncLes verrous de méthode synchrones sont accessibles sur la méthode, tandis que les verrous de bloc synchronisés sont accessibles sur l'objet.
class MathService { void getSumOfArray(int[] numbers) { synchronized (this){ int sum = 0; for (int number : numbers) { System.out.println(Thread.currentThread() .getName() + " adds " + sum + " to " + number + " to get -> " + (sum += number)); try { Thread.sleep(500); } catch (InterruptedException e) { throw new RuntimeException(e); } } } } } public class Synchronization { public static void main(String[] args) { MathService mathService = new MathService(); Thread threadOne = new Thread(() -> mathService.getSumOfArray(new int[]{10, 11, 12})); Thread threadTwo = new Thread(() -> mathService.getSumOfArray(new int[]{20, 21, 22})); threadOne.start(); threadTwo.start(); } }
Explication du code :
En exécutant ce code, vous remarquerez qu'il fonctionne sans aucune interférence. Dans la méthode synchronisée, le verrou est appliqué par la méthode, mais dans le bloc synchronisé, le verrou est appliqué par l'objet. Assurez-vous que la sortie est comme indiqué ci-dessous.
Sortie :
Thread-0 adds 0 to 10 to get -> 10 Thread-0 adds 10 to 11 to get -> 21 Thread-0 adds 21 to 12 to get -> 33 Thread-1 adds 0 to 20 to get -> 20 Thread-1 adds 20 to 21 to get -> 41 Thread-1 adds 41 to 22 to get -> 63
Explication du code:
Lorsque vous exécutez ce code, vous remarquerez qu’il fonctionne sans interférence, ce à quoi nous nous attendions. Dans la méthode synchronisée, le verrou est appliqué par la méthode, mais dans la méthode de bloc synchronisé, le verrou est appliqué par l'objet.
Utiliser la synchronisation statique
In Java Synchronisation : s'il y a plus d'un objet, deux threads peuvent acquérir les verrous et entrer dans un bloc synchronisé ou un bloc, avec un verrou séparé pour chaque objet. Pour éviter cela, une synchronisation statique peut être utilisée. Syncles mots-clés hronisés seront utilisés avant les méthodes statiques.
Remarque : Dans la synchronisation statique, le verrouillage de l'accès concerne la classe, et non l'objet et la méthode.
Code pour démontrer le problème du verrouillage de plusieurs objets
class MathService { synchronized void getSumOfArray(int[] numbers) { int sum = 0; for (int number : numbers) { System.out.println(Thread.currentThread() .getName() + " adds " + sum + " to " + number + " to get -> " + (sum += number)); try { Thread.sleep(500); } catch (InterruptedException e) { throw new RuntimeException(e); } } } } public class Synchronization { public static void main(String[] args) { MathService mathService = new MathService(); MathService mathService1 = new MathService(); Thread threadOne = new Thread(() -> mathService.getSumOfArray(new int[]{10, 11, 12})); Thread threadTwo = new Thread(() -> mathService.getSumOfArray(new int[]{20, 21, 22})); Thread threadThree = new Thread(() -> mathService1.getSumOfArray(new int[]{10, 11, 12})); Thread threadFour = new Thread(() -> mathService1.getSumOfArray(new int[]{20, 21, 22})); threadOne.start(); threadTwo.start(); threadThree.start(); threadFour.start(); } }
Explication du code:
Lorsque nous créons une autre instance de `MathService`, nous introduisons des interférences dans les threads car ils seront entrelacés avec les deux objets. Notez que le thread « 0 » et le thread « 2 » sont entrelacés avec les deux objets, tandis que les threads « 1 » et « 3 » sont entrelacés avec les deux objets.
Sortie :
Thread-0 adds 0 to 10 to get -> 10 Thread-2 adds 0 to 10 to get -> 10 Thread-0 adds 10 to 11 to get -> 21 Thread-2 adds 10 to 11 to get -> 21 Thread-0 adds 21 to 12 to get -> 33 Thread-2 adds 21 to 12 to get -> 33 Thread-1 adds 0 to 20 to get -> 20 Thread-3 adds 0 to 20 to get -> 20 Thread-1 adds 20 to 21 to get -> 41 Thread-3 adds 20 to 21 to get -> 41 Thread-1 adds 41 to 22 to get -> 63 Thread-3 adds 41 to 22 to get -> 63
Même code en utilisant la méthode statique synchronisée
class MathService { synchronized static void getSumOfArray(int[] numbers) { int sum = 0; for (int number : numbers) { System.out.println(Thread.currentThread() .getName() + " adds " + sum + " to " + number + " to get -> " + (sum += number)); try { Thread.sleep(500); } catch (InterruptedException e) { throw new RuntimeException(e); } } } } public class Synchronization { public static void main(String[] args) { MathService mathService = new MathService(); MathService mathService1 = new MathService(); Thread threadOne = new Thread(() -> mathService.getSumOfArray(new int[]{10, 11, 12})); Thread threadTwo = new Thread(() -> mathService.getSumOfArray(new int[]{20, 21, 22})); Thread threadThree = new Thread(() -> mathService1.getSumOfArray(new int[]{10, 11, 12})); Thread threadFour = new Thread(() -> mathService1.getSumOfArray(new int[]{20, 21, 22})); threadOne.start(); threadTwo.start(); threadThree.start(); threadFour.start(); } }
Exécutez le code ci-dessus et notez que nous avons maintenant éliminé les interférences de thread. La sortie du code est présentée ci-dessous.
Sortie :
Thread-0 adds 0 to 10 to get -> 10 Thread-0 adds 10 to 11 to get -> 21 Thread-0 adds 21 to 12 to get -> 33 Thread-3 adds 0 to 20 to get -> 20 Thread-3 adds 20 to 21 to get -> 41 Thread-3 adds 41 to 22 to get -> 63 Thread-2 adds 0 to 10 to get -> 10 Thread-2 adds 10 to 11 to get -> 21 Thread-2 adds 21 to 12 to get -> 33 Thread-1 adds 0 to 20 to get -> 20 Thread-1 adds 20 to 21 to get -> 41 Thread-1 adds 41 to 22 to get -> 63
Avantages de l'utilisation de la synchronisation
Voici les avantages de travailler avec des applications simultanées :
- L’objectif principal de la synchronisation dans Java est d'empêcher les données incohérentes en empêchant les interférences entre les threads.
- Le mot clé synchronisé dans Java fournit un verrouillage, qui garantit un accès mutuellement exclusif à la ressource partagée et empêche la course aux données.
- Cela empêche également la réorganisation des instructions de code par le compilateur, ce qui peut provoquer un subtil problème de concurrence si nous n'utilisons pas de mots-clés volatils ou synchronisés.
- SyncLe mot-clé hronized lit les données de la mémoire principale plutôt que du cache et lorsqu'il libère le verrou.
- Il supprime également les opérations d'écriture de la mémoire principale, éliminant ainsi les erreurs d'incohérence de la mémoire.
Inconvénients de SyncMécanisme d'hronisation
SyncLes mécanismes de hronisation ont des performances médiocres.
Par exemple
- Supposons qu’il existe cinq processus : A1, A2, A3, A4 et A5.
- Ils attendent que les ressources partagées accèdent à un thread à la fois.
- Tous les processus restent en attente, donc le dernier dans la file d'attente doit attendre que tous les autres processus soient terminés.
Résumé
- SyncL'hronisation fait référence à la possibilité de contrôler l'accès de plusieurs threads à n'importe quelle ressource partagée.
- Java dispose de deux types de méthodes de synchronisation : 1) Synchronisation des processus et 2) Synchronisation des threads.
- Verrouiller Java est construit autour d’une entité interne appelée moniteur ou verrou.
- Un programme multithread est une méthode ou un bloc protégé des interférences d'autres threads partageant la même ressource indiquée à l'aide du mot-clé « synchronized ».
- Toute méthode déclarée comme synchronisée est appelée méthode synchronisée.
- In Java, les verrous de méthode synchronisés sont accessibles sur la méthode, tandis que les verrous de bloc synchronisés sont accessibles sur l'objet.
- Dans la synchronisation statique, le verrouillage de l'accès concerne la classe, et non l'objet et la méthode.
- L’objectif principal de la synchronisation dans Java est d'empêcher les données incohérentes en empêchant les interférences entre les threads.
- Le plus gros inconvénient de cette méthode est que tous les processus sont maintenus en attente, de sorte que le dernier dans la file d'attente doit attendre que tous les autres processus soient terminés.