Art Java programmation concurrente (7) sémantique de mémoire volatile et la mise en œuvre

Lorsque la variable partagée déclarée volatile, la lecture de cette variable / écriture sera spéciale.

Les caractéristiques de volatilité

(1) Visibilité: lecture d'un variables volatiles, toujours en mesure de voir (tout thread) de la dernière écriture de variable volatile
atome (2) de: lecture d'une écriture / volatile variable unique atomique, mais un tel volatils composites similaires ++ opérations atomiques sans avoir

écriture volatile - passe-avant la lecture de la relation établie

écriture variable volatile - communication entre les fils de lecture peut être obtenue.
Du point de vue sémantique mémoire, volatile écriture - lecture et libération de verrouillage - l' obtention de la même mémoire à effet: les verrous de libération volatiles et avoir écrit le même mémoire sémantique; serrure lecture acquisition mémoire volatile a la même sémantique

class VolatileExample {
    int a = 0;
    volatile boolean flag = false;
    public void writer() {
        a = 1;         1 
    flag = true;          2 
    }
    public void reader() { 
        if (flag) {         3 
            int i = a;        4 
        …… }
    }
}

Après fil Un procédé exécution est supposée écrivain (), le fil B exécuté procédé Reader (). Le arrive, avant la règle, qui se passe-avant relation établie , ce processus peut être divisé en trois catégories:
(1) Les règles de séquence de programme, 1 arrive-avant 2; 3 arrive-avant 4.
(2) La règle volatile, 2 arrive-avant 3
(3) se produit avant-règles de transfert, se produit une avant-4
Insérer ici l'image Description
après que le fil a une variable à écrire, un filetage variable B lit la variable volatile. Un fil avant d' écrire des variables volatiles toutes les variables partagées visibles, du fil B après avoir lu la même variable volatile, sera immédiatement visible pour enfiler B.

écriture volatile - lecture de la mémoire sémantique

Lors de l' écriture d' une variable volatile, JMM correspondra à la mémoire locale fil des valeurs de variables partagées vidées de la mémoire principale
lors de la lecture d' une variable volatile, JMM sera le fil correspondant mémoire locale est désactivé. Sujet suivant lit de la mémoire principale de partager cette variable.
Insérer ici l'image Description

résumé lecture-écriture volatile

(1) Un fil d' écriture d' une variable volatile, est essentiellement un thread A envoie un message (leurs variables partagées à apporter des modifications) à lire à côté de ces variables volatiles un de fil.
(2) la lecture d' un filetage variable volatile B, le fil B est essentiellement accepté (avant d' écrire cette quantité variable volatile de modifications apportées à la variable partagée) message envoyé par un fil avant.
(3) un filetage variable volatile A, puis le fil B lit les variables volatiles, le processus est essentiellement le fil A envoie un message au fil B à la mémoire principale.

sémantique de mise en œuvre de la mémoire volatile

Table JMM est pour le compilateur développé par la table volatile de classement lourd.
Insérer ici l'image Description
(1) lorsque la deuxième opération est un temps d'écriture volatile , peu importe ce qui est la première opération qui ne peut pas être réorganisées. Cette règle garantit que l' opération d'écriture volatile ne sera pas compilé jusqu'à découragé après la commande d'écriture.
(2) lorsque la première opération est un temps de lecture volatile , peu importe ce qui est la deuxième opération, ne peut pas être réorganisées. Cette règle garantit que l' opération de lecture volatile ne sera pas compilé après la commande découragées à lire avant.
(3) lorsque la première opération est une écriture volatile , la seconde opération est une lecture volatile, aucun réarrangement.

Insérez la barrière de mémoire

Afin d'atteindre la sémantique de mémoire volatile, lorsque le compilateur bytecode de génération sera inséré dans la barrière de la mémoire de séquence d'instructions pour inhiber un type particulier de réordonnancement de processeur.
(1) opération d'écriture pour insérer une barrière à l'avant StoreStore chaque volatile.
(2) une opération de ré-écriture est inséré dans chaque barrière StoreLoad volatile.
(3) l' insertion d' une barrière de LoadLoad volatile après chaque opération de lecture.
(4) l' insertion d' une barrière de LoadStore volatile après chaque opération de lecture.
commande d' écriture des barrières de mémoire volatile séquence générée est insérée à un schéma conservateur stratégie d'
Insérer ici l'image Description
écriture volatile derrière barrière StoreLoad. L'effet de cette barrière est d'éviter le retour d'écriture volatile et peut avoir réordonnancement lecture / écriture volatile.
Parce que le compilateur détermine souvent ne peut pas avec précision si un besoin StoreLoad arrière d'écriture volatile pour insérer une barrière (par exemple, une méthode d'écriture volatile immédiatement après le retour).
Afin d'assurer d'obtenir une mémoire volatile sémantiquement correcte, JMM prendre une stratégie prudente: Dans chaque dos d'écriture volatile, ou insérez une barrière StoreLoad devant chaque lecture volatile.
écriture volatile - motif d'usage courant sont lues de la mémoire sémantique : un fil d'écriture pour écrire des variables volatiles, les fils de lecture multiples de lecture de la même variable volatile. Lorsque le nombre de threads à lire beaucoup plus que d' écrire un fil, sélectionnez barrière Insérer StoreLoad après écriture volatile apportera une amélioration considérable de l' efficacité.
JMM est une caractéristique sur la mise en œuvre : d' abord assurer l'exactitude, puis aller à la recherche de l' efficacité.

Type barrière Type d'instruction explication
barrières LoadLoad CHARGER1; LoadLoad; Load2 CHARGER1 assurer que les données Load2 chargées avant toute la charge de l'instruction de chargement ultérieur
barrières StoreStore Store1; StoreStore; magasin2 Le stockage des données pour assurer store1 visible à d'autres processeurs (mémoire de rafraîchissement) avant magasin2 et toutes les instructions de magasin ultérieure
barrières LoadStore CHARGER1; LoadStore; magasin2 Load1 salé magasin2 assurer le chargement de données et le stockage de toutes les instructions suivantes sont rincées à la mémoire
barrières StoreLoad Store1; Grande charge; Load2 Store1 assurer que les données devient visible (reportez-vous à rafraîchir la mémoire) est d'abord chargé dans Load2 et toutes les instructions de charge ultérieure à d'autres processeurs. Toutes les instructions d'accès mémoire (instructions de chargement et de stockage) Barrières StoreLoad sera après la barrière avant l'achèvement, avant la mise en œuvre de l'instruction d'accès mémoire après la barrière

StoreLoad obstacles est un des obstacles « polyvalents », il a aussi l'effet de trois autres obstacles. La plupart support multi-processeurs modernes pour la barrière. La mise en œuvre de la surcharge de la barrière sera très cher, parce que le processeur actuel veulent généralement écrire toutes les données dans la mémoire tampon à la mémoire de rafraîchissement (tampon entièrement Flush)

Exemples

class VolatileBarrierExample {
    int a;
    volatile int v1 = 1;
    volatile int v2 = 2;
    void readAndWrite() {
        int i = v1;  第一个volatileint j = v2;  第二个volatile读 
        a = i + j;  普通写 v1 = i + 1; // 第一个volatile写 
        v2 = j * 2;  第二个 volatile} 
    ...... 其他方法 
}

Pour la méthode readAndWrite (), le compilateur génère bytecode lorsque optimisé de la manière suivante.
Insérer ici l'image Description
Le dernier obstacle à sauter dans StoreLoad omis. Parce que , après la deuxième méthodes d'écriture volatiles reviennent immédiatement. A cette époque, le compilateur ne peut pas déterminer avec précision s'il y aura des volatiles lire ou écrire plus tard, pour des raisons de sécurité, le compilateur généralement insérer ici une barrière StoreLoad.

Publié 24 articles originaux · louange gagné 1 · vues 545

Je suppose que tu aimes

Origine blog.csdn.net/qq_45366515/article/details/105139240
conseillé
Classement