Un modèle qui limite le traitement afin qu'un seul thread puisse s'exécuter à la fois. Le modèle d'exécution à thread unique est parfois appelé ** Section critique ** ou ** Région critique **.
(Code qui fonctionne comme prévu et code qui ne fonctionne pas comme prévu)
Dans le modèle d'exécution à thread unique, une classe avec le rôle de ** Shared Resourece ** apparaît. Le rôle SharedResourece a plusieurs méthodes, qui sont classées dans les deux types suivants.
--safeMethod: Une méthode qui peut être appelée à partir de plusieurs threads en même temps sans aucun problème. --unsafeMethod: Une méthode qui doit être protégée car il n'est pas possible d'être appelée par plusieurs threads en même temps.
Le modèle d'exécution à thread unique protège unsafeMethad de sorte qu'il ne soit accessible que par un thread à la fois. En Java, le gardiennage est réalisé en en faisant une méthode synchronisée. La plage qui doit être exploitée dans un seul thread est appelée la ** section critique **.
À propos, Java fournit une méthode pour rendre la classe de collection sûre pour les threads.
--synchronizedCollection, méthode --synchronizedList, méthode --synchronizedMap, méthode --synchronizedSet, méthode --synchronizedSortedMap, méthode --synchronizedSoretedSet, méthode
** Ceci est très important, alors écrivez-le attentivement. ** **
Le blocage dans l'exécution à thread unique se produit lorsque toutes les conditions suivantes sont remplies:
Par exemple, supposons que A et B mangent le riz devant eux. Vous avez besoin d'une cuillère et d'une fourchette pour manger. Supposons que A prenne une cuillère et B une fourchette. A ce moment, A attend que B mette la fourchette et B attend que A mette la cuillère. Un blocage sans issue se produit. Dans cet exemple
Par conséquent, un verrou mort s'est produit. Dans cet exemple, essayez de briser la condition 1, 2 ou 3.
Essayez de casser 1. Vous n'avez besoin que d'une cuillère pour manger. Avec cela, le blocage mort ne se produit pas. Essayez de casser 2. Arrêtez d'aller chercher la fourchette en tenant la cuillère. Si vous pouvez manger avec une cuillère, manger avec une cuillère, et lorsque vous avez fini de manger, mettez la cuillère une fois et allez chercher la fourchette suivante. Cela ne provoque pas de blocage. Essayez de casser 3. Assurez-vous de décider que vous devez prendre la cuillère et la fourchette dans cet ordre. Ensuite, quand A prend la cuillère, B peut prendre la fourchette car B doit attendre que la cuillère soit placée (puisque B ne prend jamais la fourchette). Aucun verrou mort ne se produit.
Même si le rôle SharedResource est créé exactement pour garantir la sécurité, il existe un risque que la sécurité soit détruite par le sous-classement. L'héritage peut causer des problèmes gênants dans la programmation multithread. Ceci est appelé ** erreur d'héritage **.
En général, le modèle d'exécution à thread unique dégrade les performances.
--Raison 1: il faut du temps pour acquérir le verrou --Raison 2: Parce que vous devez attendre en raison d'une collision de threads
Par exemple, le code suivant est-il le même que le code utilisant synchronized?
void method() {
lock(); //Supposons qu'il existe une telle méthode
...
unlock(); //Supposons qu'il existe une telle méthode
}
La réponse n'est pas la même. Cela est dû au fait que le verrou n'est pas libéré lorsqu'un retour ou une gestion d'exception est exécuté entre lock () et unlock (). D'un autre côté, la méthode synchronisée et le bloc synchronisé libèrent le verrou en quittant {}, donc que vous retourniez ou lançiez une exception au milieu, le verrou est sûrement libéré. Si vous avez une paire de méthodes comme lock () et unlock () et que vous voulez appeler unlock () quoi qu'il arrive, utilisez ** finally **.
void method
lock();
try {
...
} finally {
unlock(); //Mettez enfin le déverrouillage
}
}
Comment utiliser enfin comme ça est l'une des façons de réaliser le ** motif Avant / Après **.
Notez ce qui suit pour les méthodes synchronisées et les blocs synchronisés.
―― Que protégez-vous? -Est-ce que vous le gardez ailleurs? ―― Quelle unité devez-vous protéger?
Les substitutions et références pour le type primitif et le type de référence sont ** atomiques **. Autrement dit, si un thread effectue une affectation de n = 123 et un autre thread fait une affectation de n = 456, n sera toujours 123 ou 456. Cependant, selon les spécifications du langage Java, les affectations et références longues et doubles ne sont pas atomiques. En réalité, de nombreux systèmes de traitement du langage Java implémenteront à la fois des opérations longues et doubles comme des opérations atomiques. Avec le mot-clé ** volatile **, l'opération sur ce champ devient atomique.
L'exécution à un seul thread est un modèle dans lequel "un seul thread" exécute une certaine zone. ** Le comptage de semapho * permet à une certaine zone d'être exécutée jusqu'à "jusqu'à N threads". Le package ** java.util.concurrent ** fournit la classe ** Semaphore ** pour compter les sémaphos. Spécifiez le nombre de ressources (autorisations) dans le constructeur de Semaphore. Réservez des ressources avec la méthode ** Acquérir ** de Semaphore et publiez la version avec la méthode ** release **. L'acquisition et la libération doivent toujours être appelées par paires. Par conséquent, il est recommandé d'utiliser finally pour créer le modèle Avant / Après mentionné ci-dessus.
Relation Résumé de «Modèles de conception appris en langage Java (édition multithread)» (Partie 1) Résumé de «Modèles de conception appris en langage Java (édition multithread)» (Partie 2)
Recommended Posts