« Compréhension approfondie de la machine virtuelle Java » Chapitre 13 verrouillage de thread-safe et optimisation

annuaire

Chapitre 13 verrouillage et optimisation thread-safe

13.2 thread-safe

Ce qui est sûr de fil?

Lorsque plusieurs threads accès à un objet, voire envisager la planification et l'exécution alternative dans l'environnement de ces fils à l'exécution et ne nécessite pas de synchronisation supplémentaire, ou effectuer toute autre opération en appelant la coordination, appelant le comportement de l'objet vous pouvez obtenir le bon résultat, que cet objet est thread-safe.

 

Code thread-safe doit avoir une fonction: le code lui-même encapsule tous les moyens nécessaires pour garantir l'exactitude (telles que la synchronisation d'exclusion mutuelle, etc.), de sorte que les appelants ne se soucient pas de problèmes multithreading, mais pas nécessairement posséder des mesures prises pour assurer une bonne multithread appeler.

 

Sécurité des threads 13.2.1 langage Java

Local: l'existence d'un accès aux données partagées entre plusieurs threads

(Papiers Brian Goetz présentés)

Thread-safe « niveau de sécurité » à trier par le faible suivi fort, divisé en cinq catégories suivantes:

Immuable, fil de sécurité absolue, le fil est relativement sûr, fil compatible, et fil hostile

1. immuable

Les objets non modifiables doivent être thread-safe. Par la suite, en raison d'objets immuables sont créés vers l'extérieur, sa visibilité ne changera jamais.

1) des données partagées est un type de données de base. Utilisez la dernière modification mot-clé pour faire en sorte que la définition du temps immuable.

2) objet de données partagées, le comportement de l'objet pour faire en sorte que ne produit pas de changement de statut d'emploi.

objets de classe sont Java.lang.String méthode immuable, substring (), remplacer () ne change pas comme la valeur d'origine, il retourne un objet String à une nouvelle configuration.

Veiller à ce que le comportement de l'objet ne modifie pas la meilleure façon propre état, l'état des variables d'objet sont déclarées finale.

Dans la classe Java immuable, String, types énumérés, Long, Double, BigInteger, BigDecimal.

 

2. Sécurité de fil absolu

« Peu importe l'environnement d'exécution, l'appelant n'a pas besoin de mesures de synchronisation supplémentaires. »

Java API noté dans une classe thread-safe, la plupart ne sont pas la sécurité absolue fil.

privé  statique vecteur <entier> = vecteur nouveau vecteur <Entier> () 
publics  statiques  vides principaux (String [] args) {
    tout ( vrai ) {
       pour ( int i = 0; i <10; i ++ ) { 
         vector.add (je); 
      } 
      Discussion removeThreadQ = nouveau fil ( nouveau Runnable () {
          publique  vide run () {
             pour ( int i = 0; i <vector.size (); i ++ ) {  
              vector.remove (i);
            } 
         }
      }; 
      Enfilez printThread = nouveau fil ( nouveau Runnable () {
           publique  vide run () {
              pour ( int i = 0; i <vector.size (); i ++ ) { 
                System.out.println (vector.get (i)) 
             } 
          } 
      }; 
      removeThread.start (); 
      printThread.start (); 
      tandis que (Thread.activeCount ()> 20 ); 
   } 
}

GET Vector (), supprimer (), la taille () sont synchronisées, mais ne prennent pas les mesures appropriées si le code de synchronisation est encore incertain.

 

3. thread-safe relative

Thread-safe dans le sens habituel, il est nécessaire de faire en sorte que cet objet est un thread séparé fonctionnement en toute sécurité, sans mesures d'assurance supplémentaires, mais pour les appels successifs dans un ordre particulier, nécessitent l'utilisation de moyens de synchronisation supplémentaires lorsque vous appelez pour assurer l'exactitude de l'appel.

Java, la plupart des classes thread-safe sont de ce type, tels que des enveloppes de méthode Vector, Hashtable, Collections.synchronizedCollection () au large de l'ensemble.

      Enfiler removeThreadQ = nouveau fil ( nouveau Runnable () {
          publique  vide run () {
             synchronisé (vecteur) {
                pour ( int i = 0; i <vector.size (); i ++ ) { 
                     vector.remove (i); 
               } 
            } 
         } 
      }; 
      discussion printThread = nouveau fil ( nouveau Runnable () {
           publique  vide run () {
              synchronisé (vecteur) {
                 pour ( inti = 0; i <vector.size (); i ++ ) { 
                  System.out.println (vector.get (i)) 
                } 
             } 
          } 
      };

 

4. fil compatible

Fait référence à l'objet lui-même est thread-safe, peut être utilisé pour assurer des objets moyens de synchronisation peuvent être utilisés dans un environnement sûr en cas d'appels simultanés.

Nous disons habituellement qu'une classe est thread-safe, se réfère à cette situation. Tels que ArrayList et HashMap.

 

Le fil hostile

Fait référence à la fin, peu importe si les appels à l'aide de mesures synchrones pour faire en sorte que l'objet ne peut pas être utilisé en toute sécurité dans un environnement multithread.

Exemples: méthode suspendent classe Thread () et méthode resume (). Deux threads simultanément par un objet thread, un appel à suspendre (), un appel à reprendre (), peut conduire à une impasse. Pour cette raison, ces deux méthodes sont

A déclaré @deprecated JDK.

 

13.2.2 mise en œuvre thread-safe

Comment mettre en œuvre un thread-safe?

La synchronisation se réfère à une pluralité de fils en même temps que les données partagées d'accès, les données partagées afin de garantir que seul un fil (ou un, à l'aide de sémaphores) à utiliser.

1. synchronisation mutex

Mutex est un moyen de synchronisation, l'application a

1) mot-clé synchronisé

Après la compilation, la formation d'instructions de monitorenter et monitorexit avant et après le code à deux octets bloc de synchronisation.

Dans la spécification JVM, lorsqu'il est exécuté instruction monitorenter, les premières tentatives pour obtenir un objet de verrouillage. Si l'objet n'a pas été verrouillé, ou seulement le verrou en cours d'objet thread, le nombre de verrouillage est incrémenté.

instruction de Monitorexit exécutée lorsque le compteur de verrouillage est décrémenté de 1 lorsque le compteur devient égal à 0, le verrou est libéré. Si le verrouillage de la cible d'acquisition échoue, le thread en cours est bloqué en attente.

 

2) Emballage java.util.concurrent rentrante serrure ReentrantLock

Par rapport synchronisé, ReentrantLock a quelques fonctionnalités avancées: interruptible attente, serrures justes, verrouillage peut être lié à un certain nombre de conditions.

Interruptible attente: fil tenant le verrou pendant une longue période de ne pas libérer le verrou, le fil d'attente pour le verrou peut renoncer à attendre, faire d'autres choses

verrouillage équitable: non équitable de verrouillage synchronisé, par défaut ReentrantLock est injuste, mais il peut être un ReentrantLock de verrouillage équitable

La liaison peut verrouiller plusieurs conditions: Condition une pluralité d'objets peuvent être liés ReentrantLock

 

2. La synchronisation non bloquante

synchronisation Mutex sera problème principal est que les problèmes blocs de fil de performance et le fil se réveille amené cette synchronisation à la synchronisation des blocs.

synchronisation Mutex pour la stratégie de verrouillage pessimiste, la tâche n'est pas des mesures de synchronisation correctes, il y aura des problèmes, peu importe qu'il y ait une concurrence à partager des données, à verrouiller.

Avec le développement de jeu d'instructions du matériel, vous pouvez utiliser la stratégie de verrouillage optimiste, ce qui est d'effectuer une opération, s'il n'y a pas de conflit de fil, l'opération sera couronnée de succès, s'il y a un concours de fil, gardez Retrying jusqu'à ce qu'il réussisse.

 

CAS

Qu'est-ce que la commande CAS?

CAS orthographe comme Compare et échange, comparer et échanger.

CAS est commande cpu (matériel connexe), qui a trois opérandes, à savoir l'adresse de mémoire, l'ancienne valeur A, la nouvelle valeur de N.

Lorsque l'instruction CAS est exécutée, que si et lorsque la valeur de l'ancienne valeur de l'adresse de la mémoire A est mis à jour à la nouvelle valeur N. Si oui ou non la mise à jour est réussie, elle retourne la valeur ancienne.

CAS inclut la mise à jour la valeur de détection de conflit d'instruction +, nécessite sémantiquement plusieurs opérations, il est nécessaire de garantir l'atomicité du matériel par une instruction de processeur.

 

Java dans le CAS.

Plusieurs méthodes sont en bas de classe à l'intérieur sun.misc.Unsafe compareAndSwapInt, compareAndSwapLong etc.,

Pour ce traitement de machine virtuelle, compilé par l'instruction de CAS est un dépendant de la plate-forme.

 

CAS vulnérabilités logiques: problème ABA

L'ancienne valeur est modifiée par la mémoire A B, puis changé à A, mais la mémoire de valeur erronée CAS n'a pas été modifié.

java.util.concurrent fournit un AtomicStampedReference pour résoudre ce problème, le principe de la variable porte le numéro de version (A1 -> B2 -> A3).

Cette classe est relativement insipide, problème ABA n'affecte pas l'exactitude de la concurrence dans la plupart des cas.

 

3. Aucun système de synchronisation

La méthode ne comporte pas le partage des données, naturelles ne nécessite pas de mesures pour assurer la précision de la synchronisation, ce code est thread-safe en soi

1) le code réentrant

L'analyse de principe de code rentrante: Si une méthode, les mêmes données d'entrée, renvoie toujours le même résultat.

 

2) Thread Local Storage

Code de données partagées est effectuée dans le même fil, la gamme visible de données partagées est limitée dans le même fil

En Java classe implémente ThreadLocal Thread Local Storage.

Exemple: Le modèle d'interaction web classique, correspond de requête à un serveur de threads, le serveur peut utiliser l'adresse de stockage local fil fil de sécurité

 

13.3 optimisation de verrouillage

Pour plus efficacement partager des données entre les threads, et résoudre les problèmes de concurrence, les techniques d'optimisation JVM pour obtenir une variété de serrures.

Y compris les verrous de rotation, serrures élimination, coarsening de serrure, léger, verrouillage partiales.

1. essorage de verrouillage de spin adaptatif

spinlocks

contexte:

1) le plus grand impact sur la performance synchronisée exclusive est bloqué OBTENUS (suspendre et reprendre le fil de fil dans les besoins en mode noyau pour terminer).

2) En même temps, dans de nombreuses applications, lorsque l'accès aux données partagées, le fil qui détient le verrou ne durera que peu de temps. Pour ce temps très court pour suspendre et reprendre le fil est très utile.

Principe: processeurs multicoeurs, deux fils ou plus peuvent être exécutées en parallèle, permettant à la demande d'exécution de fil d'une boucle de verrouillage occupée (spin) Attendre une minute, ne donnent pas le temps d'exécution de processeur pour voir si le fil de maintien du verrou nous allons bientôt libérer le verrou.

Avantages: du fait de tourner un fil d'attente pour le verrouillage et le processus ne provoque pas un changement de contexte, et donc plus efficace;

Inconvénients: le fil de spin a attendu l'exécution des processus de l'occupation du processeur, mais ne gère pas une tâche, donc si le processus est trop long, il entraînera un gaspillage de ressources CPU.

 

serrures de rotation adaptatifs

Principe: spin-spin classique adaptatif peut être le temps d'attente de manière empirique, calculer un temps d'attente raisonnable Le spin.

Si un verrou sur la même spin-attente objet gagné juste avec succès les serrures, et le fil en maintenant le verrou est en marche, le virtuel pense que cela est susceptible de tourner à nouveau avec succès, permettra la rotation d'attendre plus longtemps, par exemple 100 cycles.

Si pour une serrure, rotation réussissent rarement aussi, après l'acquisition de la serrure peut être omise lorsque le spin off processus, afin d'éviter le gaspillage des ressources.

 

2. l'élimination de verrouillage

Verrouillage signifie que la compilation d'élimination immédiate au moment de l'exécution, bien que certains du code est détecté exigences de synchronisation, mais il n'y a pas de concurrence à partager des données, ce qui éliminera le code de verrouillage.

Serrure éliminer le juge principal basé sur l'analyse d'échappement, si elle est jugée dans un morceau de code, les données ne seront pas échapper du tas par d'autres threads accès à penser qu'ils sont thread-privé, sans la nécessité de verrouillage de synchronisation.

 

3. 锁 粗 de

coarsening de verrouillage se réfère à la machine virtuelle détecte une série d'opérations sont répétées pour le même verrou d'objet, déverrouillage (même si aucun conflit de thread, provoque la synchronisation souvent mutuellement exclusives perte de performance inutile), la serrure se prolonger à toute la plage de fonctionnement synchrone séquence externe.

 

4. L'escalade de verrous

JDK1.6 version plus récente existe dans le traitement avec le concept d'escalade de verrouillage de verrouillage de synchronisation, machine virtuelle Java pour le traitement de verrouillage de synchronisation est biaisé verrouillage dès le début, l'approche de plus en plus compétitive pour la mise à niveau légère de verrouillage de verrouillage biaisé, la mise à niveau finale à la serrure des poids lourds.

Les informations de verrouillage à l'avance de l'existence d'objets Java.

 

Java sous forme d'objet suivant deux têtes (JVM à l'exemple 32)

Les objets de type non-tableau.

Où, Word ou Mark informations objet de verrouillage de hashcode stocké, Word Klass stocke un pointeur vers un objet de données de type.

L'objet est un type de matrice.

Pour les types de tableau, longueur du tableau de la longueur du réseau de mémoire.

 

Pendant le fonctionnement, les données stockées dans le mot Mark va changer le drapeau de verrouillage est changé.

1) verrouillage sollicité

« Le biais est un verrou pour des moyens de verrouillage pour optimiser le fonctionnement de son idée de base est le suivant: Si un fil pour obtenir le verrouillage, le verrou pour passer en mode de polarisation lorsque le fil demande à nouveau un verrou, donc pas besoin de faire des opérations de synchronisation. il permet d'économiser beaucoup sur le fonctionnement de l'application de verrouillage, ce qui améliore les performances des applications. par conséquent, pour les petites occasions de contention de verrouillage, ont tendance à avoir de meilleures serrures optimisation des résultats, parce que plusieurs fois de suite est très probable que la même demande avec un verrou de fil et une plus grande concurrence féroce pour le verrouillage de l'occasion, l'effet est pauvre, parce que dans une situation de concurrence, le scénario le plus probable est que chaque fois qu'un thread différent de demander la même serrure. ces modèles ont tendance à échouer, donc pourrait tout aussi bien verrouillage biaisé n'est pas activé ".

 

Quand un fil à accès bloc de synchronisation est enregistrée dans l'identifiant de fil dans l'en-tête d'objet Word Mark.

Plus tard, lors de l'entrée et la sortie du nouveau bloc synchronisé, sans l'utilisation de CAS pour le verrouillage et le déverrouillage, seule la tête de l'objet de test marque verbale dans si elle est biaisée verrouillage et id fil est votre identifiant.

1) Si le test est réussi (comme verrouillage biaisé et id fil de leur propre), ce qui indique que le fil a reçu serrure.

2) Si le test échoue

Si le mot markd dans le drapeau de verrouillage biaisé est réglé sur 1 (c.-à, le courant est biaisé verrouillage), CAS essaiera d'utiliser l'identifiant de fil mot Mark est réglé sur propre.

Si le courant ne verrouillage biaisé à l'aide contention de verrouillage du CAS.

 

2) serrure légère

Serrure de verrouillage léger:

Avant d'effectuer bloc de synchronisation, puisque la machine virtuelle Java crée un espace pour stocker les serrures, et Mark mot en-tête de l'objet copié pour verrouiller dans la trame actuelle de la pile de fil.

Ensuite, essayez de remplacer un en-tête d'objet Mark pointeur de texte pour pointer vers les verrous utilisés CAS.

En cas de succès, le thread courant d'acquérir le verrou, si elle échoue, les autres threads dans la compétition représente le verrou, le thread courant tente d'utiliser rotation pour obtenir le verrou.

 

déverrouillage de verrouillage léger:

Lorsque déverrouillé, le verrou tentera de remplacer le retour d'information d'enregistrement marque verbale à utiliser CAS.

En cas de succès, cela signifie qu'il n'y a pas de concurrence se produit, si elle échoue, ce qui indique la présence actuelle de contention de verrouillage, serrure se développe verrou lourd (verrouillage est le mutex de verrouillage des poids lourds traditionnels).

 

En faveur des serrures, verrouillage léger, poids lourd serrure

verrouillage biaisés

Rôle: pour éliminer les primitives de synchronisation de verrouillage biaisé dans une situation non concurrentielle, afin d'améliorer encore les performances du programme.

Avantages: synchronisation de verrouillage biaisé peut être améliorée, mais il n'y a pas de performance de processus concurrentiel. Mais si l'objet de verrouillage est souvent plusieurs threads en compétition, qui ont tendance à verrouiller superflu.

Applicable scène: convenable pour un seul accès de bloc de synchronisation de fil à des scènes.

En faveur de la serrure de verrouillage léger

La différence 1) et le verrou léger: serrures légères sont utilisées en cas de fonctionnement sans contention de CAS au lieu d'utiliser le mutex, réalisant ainsi la synchronisation; verrouillage polarisé est complètement abolie en l'absence de compétition cas synchrone.

2) le même point verrous légers: ils sont le verrouillage optimiste, vous ne pensez pas que tout autre conflit de verrouillage de fil lors de la synchronisation.

 

serrure légère

Contexte: « Lightweight Lock » est par rapport au « poids lourd Lock », et le verrou de blocage des poids lourds traditionnels.

Essence: Utiliser CAS pour remplacer la synchronisation mutuellement exclusifs.

Plus: Le fil ne bloque pas la concurrence, d'améliorer la vitesse de réponse du programme.

Inconvénients: threads concurrents ne peuvent toujours pas obtenir un verrou, en utilisant tour consommera CPU

serrures de verrouillage léger et poids lourd comparaison:

1) des poids lourds verrouillage pessimiste est un verrou, il est toujours considéré comme un certain nombre de fils à contention de verrouillage, de sorte que chaque fois que le traitement des données partagées, indépendamment du fait que le système actuel est vraiment un verrou de fil dans la compétition, il utilisera exclusivement pour assurer la synchronisation du fil de sécurité;

2) Le verrouillage est un verrouillage optimiste léger, ce qui verrouille pense que la probabilité de l'existence de la concurrence est relativement faible, de sorte qu'il n'utilise pas une synchronisation mutex, mais l'utilisation de l'opération CAS pour acquérir le verrou, ce qui pourrait réduire « l'usage exclusif de la synchronisation mutex « apporter les frais généraux de performance.


verrou lourd

Avantages: la concurrence ne pas utiliser fil de rotation, ne consomment pas CPU

Inconvénients: fil est bloqué, le temps de réponse lent

 

Je suppose que tu aimes

Origine www.cnblogs.com/yeyang/p/12580649.html
conseillé
Classement