En Java, le mot-clé synchronisé et le verrouillage de verrouillage sont utilisés pour réaliser un contrôle d'accès simultané des ressources. Seuls les threads uniques sont autorisés à entrer dans la zone critique pour accéder aux ressources (à l'exception des verrous de lecture). L'objectif principal de ce sous-contrôle est de résoudre le problème de l'incohérence des données causée par plusieurs threads simultanément avec la même ressource. Dans un autre scénario, une ressource a plusieurs copies à utiliser en même temps, telles que plusieurs imprimantes dans la salle d'imprimante et plusieurs fosses à utiliser en même temps. Dans ce cas, Java fournit un autre contrôle d'accès simultané - un contrôle d'accès simultané pour plusieurs copies de la ressource, et le sémaphore utilisé aujourd'hui en fait partie.
Java peut détecter les problèmes potentiels de sécurité des threads dans notre système de la manière la plus rapide grâce à la simulation de code. Ici, le sémaphore (sémaphore) et le compte à rebours (verrouillage) sont utilisés avec ExecutorService (thread pool) pour la simulation. L'introduction principale est la suivante:
1. Semaphore
Cette classe sera fournie après JDK 1.5
Le sémaphore est un sémaphore basé sur le décompte. Il peut définir un seuil, en fonction de cela, plusieurs threads rivalisent pour obtenir le signal de licence et le retourner après avoir fait leur propre application. Après avoir dépassé le seuil, l'application du thread pour le signal de licence sera bloquée. Le sémaphore peut être utilisé pour construire certains pools d'objets, des pools de ressources, etc., tels que les pools de connexion de base de données. Nous pouvons également créer du sémaphore avec un nombre de 1, en l'utilisant comme mécanisme similaire aux serrures mutex. Ceci est également appelé sémaphore binaire, indiquant deux états de mutex.
2. Countdownlatch
Cette classe sera fournie après JDK 1.5.
La classe CountdownLatch peut faire attendre un fil d'attente que d'autres threads terminent leur travail respectif avant de s'exécuter. Par exemple, le thread principal de l'application souhaite s'exécuter après le thread responsable du démarrage du service Framework a lancé tous les services Framework.
CountdownLatch est implémenté via un compteur, et la valeur initiale du compteur est le nombre de threads. Chaque fois qu'un thread termine sa propre tâche, la valeur de comptoir est décrémentée de 1. Lorsque la valeur de comptoir atteint 0, cela signifie que tous les threads ont terminé la tâche, puis les threads en attente sur le verrou peuvent reprendre l'exécution de la tâche.
Comme indiqué dans la figure ci-dessous:
Les deux classes ci-dessus peuvent être utilisées en combinaison pour obtenir l'effet de la simulation de concurrence élevée. Le code suivant est utilisé pour donner un exemple:
Modules de package; import java.util.concurrent.countownlatch; import java.util.concurrent.executorService; import java.util.concurrent.execcutors; import java.util.concurrent.semaphore; public class compating // Nombre de threads exécutés simultanément en même temps public static int threadTotal = 200; public static int count = 0; public static void main (String [] args) lève une exception {ExecutorService ExecutorService = exécutor.NewCachedThreadPool (); // semi-conducteur, utilisé pour contrôler le nombre de threads simultanés ici Semaphore final Semaphore = nouveau sémaphore (ThreadTotal); // verrouillage, qui peut réaliser la décrémentation du compteur final CountdownLatch CountdownLatch = new CountDownLatch (clientTotal); pour (int i = 0; i <clientTotal; i ++) {exécutorService.execute (() -> {try {// Exécuter cette méthode pour obtenir l'autorisation d'exécution. Lorsque le nombre total de licences inédites ne dépasse 200, // permettre des passes, sinon les blocs de threads et les attentes jusqu'à ce que le licence ne soit obtenu. SeamAphore.ACQUIRE (); Add (); / libérer le licence Semit. } catch (exception e) {//log.error("exception ", e); e.PrintStackTrace (); } CountdownLatch.Await (); // Blocs de threads, et le bloc n'est pas libéré tant que la valeur de verrouillage n'est pas 0. Continuez à exécuter ExecutorService.shutdown (); log.info ("count: {}", count); } private static void add () {count ++; }}Comme le montre la méthode ci-dessus, 5000 demandes sont simulées et 200 opérations simultanées représentent jusqu'à 200 opérations simultanées en même temps. Observez les résultats finaux et constatez que les résultats sont différents pour chaque fois et sont incompatibles avec les attentes. Le résultat est le suivant:
22: 18: 26.449 [Main] Modules d'informations.Countexample - Count: 4997
22: 18: 26.449 [Main] Modules d'information.Countexample - Count: 5000
22: 18: 26.449 [Main] Modules d'informations.Countexample - Count: 4995
22: 18: 26.449 [Main] Modules d'informations.Countexample - Count: 4998
Conclusion finale: la méthode ADD n'est pas
Ensuite, comment assurer la sécurité du thread de la méthode ADD, modifiez la méthode ADD comme suit:
private static void add () {count.incrementAndget ();}Les résultats de l'exécution sont les suivants:
22: 18: 26.449 [Main] Modules d'information.Countexample - Count: 5000
22: 18: 26.449 [Main] Modules d'information.Countexample - Count: 5000
22: 18: 26.449 [Main] Modules d'information.Countexample - Count: 5000
22: 18: 26.449 [Main] Modules d'information.Countexample - Count: 5000
22: 18: 26.449 [Main] Modules d'information.Countexample - Count: 5000
22: 18: 26.449 [Main] Modules d'information.Countexample - Count: 5000
22: 18: 26.449 [Main] Modules d'information.Countexample - Count: 5000
22: 18: 26.449 [Main] Modules d'information.Countexample - Count: 5000
Conclusion finale: la méthode ADD modifiée
Ce qui précède est tout le contenu de cet article. J'espère que cela sera utile à l'apprentissage de tous et j'espère que tout le monde soutiendra davantage Wulin.com.