comment comprendre par exemple volatile spécification du langage Java?

Tim :

Je pense par exemple de volatile dans la spécification Java est un peu mal.

Dans 8.3.1.4. Les champs volatils, il est dit

class Test {
    static int i = 0, j = 0;
    static void one() { i++; j++; }
    static void two() {
        System.out.println("i=" + i + " j=" + j);
    }
}

... puis méthode en deux temps en temps pourrait imprimer une valeur pour j qui est supérieure à la valeur de i, parce que l'exemple ne comprend pas la synchronisation et, selon les règles expliquées in§17.4, les valeurs partagées de i et j peuvent être mis à jour sur commande.

Je pense que même si ces mises à jour sont dans l' ordre, la méthode peut encore deux voir j plus que moi, puisque System.out.println("i=" + i + " j=" + j)n'est pas atomique, et i est lu avant j.

Procédé selon deux est la même que

read i
read j

Il est donc possible que

read i
i++
j++
read j

Dans ce cas, la méthode de deux voir une valeur pour j qui est supérieure à i, mais les mises à jour ne sont pas hors de l'ordre.

Donc, de l'ordre n'est pas la seule raison de voir j> i

Devrait - il être System.out.println("j=" + j + " i=" + i);?

Cette fois hors d'usage est la seule raison de voir j> i

Holger:

Les exemples sont plus que « un peu mal ».

Tout d' abord, vous avez raison que , même sans réordonnancement, jpeut apparaître plus que idans cet exemple. Ceci est même reconnu plus tard dans le même exemple :

Une autre approche serait de déclarer iet jd'être volatile:

class Test {
    static volatile int i = 0, j = 0;
    static void one() { i++; j++; }
    static void two() {
        System.out.println("i=" + i + " j=" + j);
    }
}

Cela permet à la méthode oneet la méthode twoà exécuter en même temps, mais garantit que les accès aux valeurs partagées pour iet jse produisent exactement autant de fois, et dans le même ordre, comme ils semblent se produire lors de l' exécution du texte du programme par chaque fil. Par conséquent, la valeur partagée jest jamais supérieure à celle pour i, parce que chaque mise à jour idoit se refléter dans la valeur partagée iavant la mise à jour jse produit. Il est possible, cependant, que toute invocation donnée de la méthode twopeut observer une valeur jbien supérieure à la valeur observée pour i, parce que la méthode onepeut être exécuté plusieurs fois entre le moment où la méthode twova chercher la valeur deiet le moment où la méthode tworécupère la valeur de j.

Bien sûr, il est abstruse de dire « la valeur partagée jest jamais supérieure à celle pouri », juste pour dire droit dans la phrase suivante « Il est possible ... [à] observer une valeur jbien supérieure à la valeur observée pouri ».

Donc , jne dépasse jamais i, sauf quand il est observé que beaucoup plus grand que i? Est - il censé dire que « un peu plus » est impossible?

Bien sûr que non. Cette déclaration n'a pas de sens et semble être le résultat d'essayer de séparer une vérité objective comme « la valeur partagée » de « la valeur observée » alors qu'en fait, il n'y a qu'un comportement observable dans un programme.

Ceci est illustré par la phrase erronée:

Cela permet à la méthode et de méthode de deux à exécuter en même temps, mais garantit que les accès aux valeurs partagées pour iet jse produisent exactement autant de fois, et dans le même ordre, comme ils semblent se produire lors de l' exécution du texte du programme par chaque fil.

Même avec les volatilevariables, il n'y a aucune garantie. Tout ce que la machine virtuelle Java doit garantir, est que le comportement observé ne contredit pas la spécification, de sorte que lorsque vous invoquez one()mille fois dans une boucle, par exemple, un optimiseur peut toujours remplacer avec un incrément atomique par des milliers, si elle peut empêcher la possibilité d'un autre thread témoin de la présence d'une telle optimisation (autre que déduisant de la vitesse plus élevée).

En d' autres termes, combien de fois est qu'accède, n'est pas observable et , par conséquent, non spécifié une variable (resp. Son emplacement de mémoire). Peu importe de toute façon. Tout ce qui est important pour un programmeur d'application, est que jpeut être supérieur à i, si les variables sont déclarées volatileou non.

Permutant l'ordre du lit de iet à l' jintérieur two()pourrait faire un meilleur exemple, mais je pense, il serait préférable, si JLS §8.3.1.2 n'a pas essayé d'expliquer la signification des volatilefamilièrement, mais juste dit qu'il impose une sémantique spéciale selon au modèle de mémoire et de gauche à la JMM pour l' expliquer de manière formellement correcte.

Les programmeurs ne sont pas censés maître juste concurrency en lisant 8.3.1.4, si l'exemple est inutile ici. (Dans le meilleur des cas, le pire des cas serait de créer l'impression que cet exemple était suffisante pour comprendre la question).

Je suppose que tu aimes

Origine http://43.154.161.224:23101/article/api/json?id=178894&siteId=1
conseillé
Classement