Principe de réalisation de la visibilité du cache volatile (les étapes spécifiques du fonctionnement atomique des données JMM)

Modèle de mémoire Java:

Insérez la description de l'image ici

Opération atomique de données JMM:

Insérez la description de l'image ici

Etapes spécifiques:

Insérez la description de l'image ici

Thread 1: Lisez d'abord la variable initFlag lue, puis chargez-la dans la mémoire de travail, utilisez utilise thread 1 pour exécuter le code! InitFlag

Thread 2: commencez par lire la variable initFlag lue, puis chargez dans la mémoire de travail, utilisez utilise thread 2 pour exécuter le code initFlag = true, puis attribuez une ré-affectation, stockez les magasins et les écritures dans la mémoire principale, écrivez les écritures dans la mémoire principale variable. (Le thread 2 verrouille le verrou de la ligne de cache et se déverrouille après l'écriture dans la mémoire principale pour empêcher que initFlag ne soit lu comme faux par le thread 1 avant d'écrire dans la mémoire principale.)

Thread 1: comme initFlag est modifié par volatile, le protocole de cohérence du cache MESI est utilisé, le mécanisme de reniflage du bus CPU du thread 1 surveille la modification de la valeur initFlag, initFlag = false devient vrai dans le thread 1 et quitte la boucle pour continuer l'exécution, ce qui reflète le fonctionnement synchrone de plusieurs threads Visibilité d'une copie de la variable partagée . Si l'initFlag n'est pas modifié par volatile, le thread 1 ne percevra pas le changement dans initFlag et la boucle ne s'arrêtera pas.

Le code dans l'image:

public class VolatileVisibilityTest {
    
    
    //volatile变量,用来确保将变量的更新操作通知到其他线程。
    private static volatile boolean initFlag = false;

    public static void main(String[] args) throws InterruptedException {
    
    
        new Thread(new Runnable() {
    
    
            @Override
            public void run() {
    
    
                System.out.println("waiting data...");
                while (!initFlag) {
    
    

                }
                System.out.println("==============success");
            }
        }).start();

        Thread.sleep(2000);

        new Thread(new Runnable() {
    
    
            @Override
            public void run() {
    
    
                prepareData();
            }
        }).start();
    }
        public static void prepareData(){
    
    
            System.out.println("preparing data...");
            initFlag = true;
            System.out.println("prepare data end...");
        }
}

Résolvez le problème de l'incohérence du cache jmm:

Insérez la description de l'image ici

Insérez la description de l'image ici

Insérez la description de l'image ici


Verrouillage du bus: le
verrouillage et le déverrouillage verrouillent la mémoire principale, le verrouillage du bus n'est généralement pas utilisé, l'efficacité est trop faible et similaire à celle d'un thread unique. Utilisez généralement le protocole de cohérence du cache MESI.
Insérez la description de l'image ici
Insérez la description de l'image ici

Je suppose que tu aimes

Origine blog.csdn.net/weixin_41699562/article/details/104150671
conseillé
Classement