28 votes

Valeur de retour de l'opérateur d'affectation dans le code concurrent

Étant donné la classe suivante :

classFoo{
  publicvolatileintnumber;

  publicintmethod1(){
    intret=number=1;
    returnret;
  }

  publicintmethod2(){
    intret=number=2;
    returnret;
  }
}

et étant donné que plusieurs threads appellent method1() y method2() simultanément sur le même Foo Par exemple, un appel à la méthode1() peut-il retourner autre chose que 1 ?

12voto

Ted Hopp Points 122617

Je pense que la réponse dépend du compilateur. Le langage spécifie :

Au moment de l'exécution, le résultat de l'expression d'affectation est la valeur de la variable après l'affectation.

Je suppose que, théoriquement, la valeur pourrait être modifiée avant que la deuxième affectation (la plus à gauche) ne se produise.

Cependant, avec le compilateur javac de Sun, method1 va se transformer en :

0:   aload_0
1:   iconst_1
2:   dup_x1
3:   putfield        #2; //Field number:I
6:   istore_1
7:   iload_1
8:   ireturn

Cela duplique la constante 1 sur la pile et le charge dans number et ensuite dans ret avant de retourner ret . Dans ce cas, il importe peu que la valeur stockée dans le fichier number est modifié avant d'être assigné à ret parce que 1 pas number est en cours d'affectation.

7voto

Bringer128 Points 3590

Le JLS 15.26 précise :

Il existe 12 opérateurs d'affectation ; tous sont syntaxiquement associatifs à droite (ils regroupent de droite à gauche). Ainsi, a=b=c signifie a=(b=c), qui attribue la valeur de c à b et attribue ensuite la valeur de b à a.

La réponse de Ted Hopp montre que le javac de Sun ne suit pas ce comportement, peut-être par souci d'optimisation.

En raison du threading, le comportement de la méthode 1 serait indéfini. Si le compilateur de Sun rend le comportement constant, il n'y a pas de rupture avec le comportement indéfini.

2voto

irreputable Points 25577

Soit la déclaration contient une lecture volatile, soit elle ne contient pas de lecture volatile. Il ne peut y avoir aucune ambiguïté ici, car la lecture volatile est très importante pour la sémantique du programme.

Si l'on peut faire confiance à javac, on peut conclure que l'instruction n'implique pas une lecture volatile de number . La valeur d'une expression d'affectation x=y est en fait juste la valeur de y (après conversions).

Nous pouvons également déduire que

    System.out.println(number=1);

n'implique pas la lecture number

    String s;

    (s="hello").length();

n'implique pas la lecture s

    x_1=x_2=...x_n=v

n'implique pas la lecture x_n, x_n-1, ... ; au lieu de cela, la valeur de v est directement affecté à x_i (après les conversions nécessaires par les types de x_n, ... x_i

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X