Modèle de mémoire Java:
Opération atomique de données JMM:
Etapes spécifiques:
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:
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.