Lors de l'exécution d'un programme, afin d'améliorer les performances, les processeurs et les compilateurs réorganisent souvent les instructions, mais elles ne peuvent pas être réorganisées à volonté. Vous ne pouvez pas les trier comme vous le souhaitez. Il doit remplir les deux conditions suivantes :
2. La réorganisation n'est pas autorisée s'il existe des dépendances de données
int a = 1 ; //A int b = 2 ; //B int c = a + b; //CLes trois opérations de A, B et C ont la relation suivante : A et B n'ont pas de dépendances de données. , Il existe une relation de dépendance des données entre B et C, donc lors de la réorganisation, A et B peuvent être triés arbitrairement, mais ils doivent être devant C. L'ordre d'exécution peut être A –> > A – > C. Mais quel que soit l’ordre d’exécution, le résultat final C est toujours égal à 3. la sémantique comme si serail protège les programmes monothread, ce qui peut garantir que le résultat final du programme est toujours cohérent dans le cadre d'une réorganisation. En fait, pour le code ci-dessus, ils ont une telle relation qui se produit avant :
public class RecordExample1 { public static void main(String[] args){ int a = 1; int b = 2; try { a = 3; //A b = 1 / 0; //B } catch (Exception e) { } finally { System.out.println("a = " + a); } } }Selon les règles de réorganisation, l'opération A et l'opération B peuvent être réorganisées si elles sont réorganisées, B lancera An. une exception se produit (/ par zéro). À ce moment, l'instruction A ne sera certainement pas exécutée. Alors a sera-t-il toujours égal à 3 ? Si vous suivez le principe comme en série, cela change le résultat du programme. En fait, la JVM effectue un traitement spécial pour les exceptions. Afin de garantir une sémantique comme si c'était une série, le mécanisme de gestion des exceptions Java effectue un traitement spécial pour la réorganisation : JIT insérera une compensation d'erreur dans l'instruction catch lors de la réorganisation. = 3), bien que cela complique la logique de cathc, le principe d'optimisation JIT est le suivant : optimiser autant que possible la logique dans le cadre du fonctionnement normal du programme, même au détriment de la complexité de la logique du bloc catch. L'impact de la réorganisation sur le multi-threadingDans un environnement monothread en raison de la sémantique comme si elle était en série, la réorganisation ne peut pas affecter le résultat final, mais qu'en est-il d'un environnement multithread ? Le code suivant (utilisation classique de volatile) :
public class RecordExample2 { int a = 0; boolean flag = false; /** * A线程执行 */ public void writer(){ a = 1; // 1 flag = true; // 2 } /** * B线程执行 */ public void read(){ if(flag){ // 3 int i = a + a; // 4 } } }Le thread A exécutewriter(), le thread B exécute read(), le thread B peut-il lire a = 1 pendant l'exécution de Woolen ? tissu? La réponse n'est pas nécessairement (
Remarque : le processeur X86 ne prend pas en charge la réorganisation en écriture-écriture. S'il fonctionne sur x86, ce sera certainement a=1. LZ ne l'a pas testé depuis longtemps et a finalement découvert après avoir vérifié les informations ).
Comme il n'y a pas de dépendance de données entre l'opération 1 et l'opération 2, la réorganisation peut être effectuée. Il n'y a pas de dépendance de données entre l'opération 3 et l'opération 4. Elles peuvent également être réorganisées, mais les opérations 3 et 4 ont une dépendance. contrôler la dépendance entre les opérations 4. Si l'opération 1 et l'opération 2 sont réordonnées : Selon cet ordre d'exécution, le thread B ne pourra certainement pas lire la valeur a définie par le thread A. La sémantique de multi-threading voici Il a été détruit par la réorganisation. L'opération 3 et l'opération 4 peuvent également être réorganisées, ce qui ne sera pas expliqué ici. Mais il existe une relation de dépendance de contrôle entre eux, car l’opération 4 ne sera exécutée que si l’opération 3 est établie. Lorsque des dépendances de contrôle existent dans le code, cela affectera le parallélisme de l'exécution de la séquence d'instructions, de sorte que les compilateurs et les processeurs utiliseront l'exécution par devinette pour surmonter l'impact des dépendances de contrôle sur le parallélisme. Si l'opération 3 et l'opération 4 sont réorganisées et que l'opération 4 est exécutée en premier, le résultat du calcul sera temporairement enregistré dans le tampon de réorganisation. Lorsque l'opération 3 est vraie, le résultat du calcul sera écrit dans la variable i via le. Dans l'analyse ci-dessus,la réorganisation n'affectera pas les résultats d'exécution d'un environnement monothread, mais détruira la sémantique d'exécution des multi-threads .
Ce qui précède est le contenu de [Java Concurrency] -----Réorganisation du modèle de mémoire Java Pour plus de contenu connexe, veuillez faire attention au site Web PHP chinois (www.php.cn) !