Ce Article parle du mot-clé "synchronisé" de Java. Si un appelant souhaite incrémenter la propriété FOO, le code suivant pour le faire n'est pas le fil-en-temps: p> MAINTENANT, ma question: p> < BlockQuote>
Pourquoi ne pas "synchronisé" sur SetFoo () empêche le gras ci-dessus
ligne? P>
blockQuote> p>
6 Réponses :
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: p>
Le mot clé (code> synchronisé code> sur les deux méthodes ne le rend pas en sécurité, car un thread peut appeler 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. p> getfoo code>, puis un autre thread pourrait appeler
getfoo code >, et chacun d'entre eux obtient le même résultat. Ensuite, chacun d'entre eux ajoutez un et appelez
setfoo code>, et le résultat final est que
foo code> 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 em>.
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 code> pourquoi?
Parce que chaque fil met à jour foo code> 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é ** ****? Code>
C'est une question de sémantique maintenant. Bien sûr, les deux threads incrémentent foo code>, 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.
Ceci est un exemple d'une condition de course de contrôle-acte.
Un scénario peut arriver comme suit: p> Cela signifierait que deux threads ont tenté d'incrémenter foo, mais il n'a que l'effet d'être incrémenté une fois. p> 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. P> p>
Piège principal de votre code est qu'il peut sembler que qui est incorrect parce que dans la réalité sortie: p> comme vous pouvez voir getfoo code> sera appelé "Intérieur"
setfoo code>.
Type de
getfoo code> est appelé avant appeler
setfoo code>. Voici l'exemple qui le montre: p>
bar code > a été invoqué avant
foo code>. Donc, dans votre cas, il est possible que deux (ou plus) threads invoquent
getfoo code> qui retournera la valeur actuelle avant d'appeler
setfoo code>. Dans ce cas, ils auront la même valeur, disons 0 et quand ils appelleront
setfoo code> ils le régleront à 1. P> p>
Vous ne pouvez pas utiliser
private volatile int foo;
volatile code> ne résoudra pas, mais l'incrémentation atomique est un bon conseil
Ce code aide-t-il?
Donc, le point est que myc.setfoo (1) code> pourrait être appelé avant
println (myc.getfoo ()) code>?