Dans le code suivant:
class A {
private int number;
public void a() {
number = 5;
}
public void b() {
while(number == 0) {
// ...
}
}
}
Si la méthode b est appelé et puis un nouveau thread est démarré, qui déclenche la méthode a, alors la méthode b n'est pas garanti jamais l'occasion de voir le changement de number
et ainsi b
peut ne jamais se terminer.
Bien sûr, nous pourrions faire number
volatile
pour résoudre ce problème. Cependant pour des raisons académiques supposons qu' volatile
n'est pas une option:
La JSR-133 Faq nous dit:
Après nous sortir d'un bloc synchronisé, nous libérer le moniteur, ce qui a pour effet de vider le cache de la mémoire principale, afin que les écritures faites par ce fil peut être visible par les autres threads. Avant que nous puissions entrer dans un bloc synchronisé, nous acquérons le moniteur, ce qui a pour effet d'invalider le processeur local cache , de sorte que les variables sont rechargés à partir de la mémoire principale.
Cela sonne comme je viens de besoin à la fois d' a
et b
d'entrer et de sortir tout synchronized
-Bloc à tous, peu importe ce que l'écran qu'ils utilisent. Plus précisément, il semble que cela...:
class A {
private int number;
public void a() {
number = 5;
synchronized(new Object()) {}
}
public void b() {
while(number == 0) {
// ...
synchronized(new Object()) {}
}
}
}
...permettrait d'éliminer le problème et vous aurez la garantie que b
va voir le changement d' a
, et donc aussi éventuellement mettre fin.
Cependant la Faq aussi indiquer clairement:
Une autre implication est que le modèle suivant, qui certaines personnes utiliser pour forcer une barrière de mémoire, ne fonctionne pas:
synchronized (new Object()) {}
C'est en fait un no-op, et le compilateur peut la supprimer entièrement, parce que le compilateur sait qu'aucun autre thread ne va synchroniser sur le même moniteur. Vous disposez d'un passe-avant la relation pour un thread pour voir les résultats de l'autre.
Maintenant que c'est déroutant. Je pensais que la synchronisation Instruction de la cause des caches de chasse d'eau. Il ne peut certainement pas de vider le cache de la mémoire principale de façon à ce que les modifications dans la mémoire principale ne peut être vu que par des fils qui se synchroniser sur le même écran, surtout que depuis volatile qui se fait de la même chose que nous n'avons pas besoin d'un moniteur, ou je me trompe? Alors pourquoi est-ce un no-op et ne cause pas d' b
à la fin de garantie?