6
votes

Threads Java "synchronisé"

Ce Article parle du mot-clé "synchronisé" de Java. xxx < / pré>

Si un appelant souhaite incrémenter la propriété FOO, le code suivant pour le faire n'est pas le fil-en-temps: xxx

si deux threads tentative Pour incrémenter le FOO en même temps, le résultat peut être que la valeur de FOO augmente par une ou deux, selon la synchronisation.

MAINTENANT, ma question: < BlockQuote>

Pourquoi ne pas "synchronisé" sur SetFoo () empêche le gras ci-dessus ligne?


0 commentaires

6 Réponses :


6
votes

Parce que vous êtes garanti Personne d'autre ne bouge que vous foo à côté de vous et que personne d'autre ne se régalait à vous, mais que vous n'êtes pas garanti que personne n'a réussi à entrer et à sortir (ou juste en) entre vous appelez get () et vous appelez ensemble ()

Vous pouvez penser à ce code aussi équivalent à ceci: xxx


0 commentaires

4
votes

Le mot clé (code> synchronisé sur les deux méthodes ne le rend pas en sécurité, car un thread peut appeler getfoo , puis un autre thread pourrait appeler getfoo , et chacun d'entre eux obtient le même résultat. Ensuite, chacun d'entre eux ajoutez un et appelez setfoo , et le résultat final est que foo est incrémenté une seule fois, au lieu de deux fois. Au fur et à mesure que votre article indique, il s'agit d'une condition de race .

Pour le faire filer en toute sécurité, la lecture et l'écriture doivent être ensemble dans le même bloc synchronisé, sans méthodes d'obtention et de définition séparées. xxx


4 commentaires

Puis chacun d'entre eux ajoutez un et appelez SETFOO, et le résultat final est que FOO est incrémenté une seule fois, au lieu de deux fois pourquoi?


Parce que chaque fil met à jour foo sur la même valeur. Par exemple, chacun d'entre eux obtient la valeur 2, chacun ajoute 1 pour obtenir 3, puis chacun d'entre eux définit la valeur à 3.


Si je comprends bien, votre relevé ne devrait-il pas être puis chacun d'entre eux ajoutez un et appelez SETFOO, et le résultat final est que FOO est incrémenté ** ****?


C'est une question de sémantique maintenant. Bien sûr, les deux threads incrémentent foo , il est donc incrémenté "deux fois". Mais à chaque fois, chaque thread l'incrémente à 3, au lieu d'un filetage l'incrémentant à 3, puis l'autre filetage l'incrémentant à 4.



6
votes

Ceci est un exemple d'une condition de course de contrôle-acte.

Un scénario peut arriver comme suit: xxx

Cela signifierait que deux threads ont tenté d'incrémenter foo, mais il n'a que l'effet d'être incrémenté une fois.

Comme d'autres réponses ont été identifiées, la synchronisation de l'incrémentation avec un bloc de bloc synchronisé sur le même objet que getfoo () et SetFoo () empêcheront Cette condition de course car les fils ne pourront pas se mêler comme ci-dessus.


0 commentaires

1
votes

Piège principal de votre code est qu'il peut sembler que getfoo sera appelé "Intérieur" setfoo . Type de xxx

qui est incorrect parce que dans la réalité getfoo est appelé avant appeler setfoo . Voici l'exemple qui le montre: xxx

sortie: xxx

comme vous pouvez voir bar a été invoqué avant foo . Donc, dans votre cas, il est possible que deux (ou plus) threads invoquent getfoo qui retournera la valeur actuelle avant d'appeler setfoo . Dans ce cas, ils auront la même valeur, disons 0 et quand ils appelleront setfoo ils le régleront à 1.


0 commentaires

0
votes

Vous ne pouvez pas utiliser

   private volatile int foo;


1 commentaires

volatile ne résoudra pas, mais l'incrémentation atomique est un bon conseil



0
votes

Ce code aide-t-il? XXX


1 commentaires

Donc, le point est que myc.setfoo (1) pourrait être appelé avant println (myc.getfoo ()) ?