public class Main{ public static void main(String[] args) throws Exception { // Creating objects for class Check(2 different objects) Check c = new Check("s1"); Check c1 = new Check("s2"); c.start();c1.start(); } } class Check extends Thread{ Check(String name){super(name);} private Integer ab = 2; public void run(){ synchronized (ab) { System.out.println(Thread.currentThread().getName()); for(int i=0;i<10;i++)System.out.print(i+" "); } } } Here i have synchronized on the variable ab. And i have created two different instances of class Check also, but i am always getting output for s1 followed by s2 or vice versa, but not mixed, why is that so? when i have already created two separate objects(in main), so two different threads, two different ab variables, so how it becomes a shared resource for the two different objects?
3 Réponses :
TL; DR - C'est à cause de J'étais initialement perplexe. Il est intéressant de noter que si vous changez p> à p> la synchronisation disparaît (vous obtenez des sorties différentes sur chaque course) . Retour avec AB comme integer code>, j'ai dirigé votre code dans le mode de débogage (avec un point d'arrêt sur la ligne de nom de thread d'impression) et trouvé ce qui suit. Voici le premier fil: p> et voici le deuxième thread. P> Notez que c'est en fait le même objet, en disant si nous examinons Pour la plupart des paramètres conventionnels, ceci inclura la valeur entier code> mise en commun. Faire un objet
code> (ie
objet ab = nouvel objet () code>) pour garantir que chaque instance de
Vérifiez code>. les autres.
integer @ 443 code>. Même si vous pensiez avoir obtenu deux objets différents, les champs
AB code> dans les deux instances de contrôle se rapportent au même objet en mémoire! Par conséquent, oui, il y a une synchronisation correcte. La question, alors, est de savoir comment dire
entier AB = 2 code> deux fois vous obtient le même
integer code> objet en mémoire. P>
Integer AB = 2 code>, vous utilisez autoboxing em>, par lequel une valeur primitive (de type
int code>) est automatiquement convertie en type d'objet correspondant
Integer code>. Cela équivaut à appeler la méthode de l'autoboxage Call: p>
integer.valueof code>, nous remarquons qu'il a un pool de valeurs dans Une certaine gamme: p>
2 code>. Ainsi, vous obtenez le même
entier code> en mémoire lorsque vous appelez cette méthode. P> p>
Vraiment intéressant. Merci beaucoup. :)
La "certaine plage" i> est de -128 à 127 par défaut. Notez que IntegerCache.High peut être modifié. Integercache.low ne peut pas.
Si vous examinez le bytecode, vous verriez probablement ce code:
LINENUMBER 15 L1 ALOAD 0 ICONST_2 INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer; PUTFIELD com/example/Check.ab : Ljava/lang/Integer;
Ceci se passe à cause de piscine de piscine à piscine forte> en Java. P>
Les entiers allant de -128 et 127 (inclus) sont utilisés de la même manière que la piscine à cordes. P>
Ainsi, lorsque vous utilisez Vous pouvez utiliser la valeur> 128 ou tout autre type d'objet afin que votre code ne soit pas synchronisé. P>
Vous pouvez regarder des réponses ici: Pourquoi le comportement de la pool entier constant change à 127 ans? pour comprendre le concept de piscine entier. P> Integer privé AB = 2; Code>, AB est partagé pour les deux objets de
check code>. p>.
Si vous avez besoin d'objets explicitement distincts, vous devez les créer explicitement. L'utilisation d'entiers plus importants vous donnera des objets distincts dans les implémentations actuelles, mais n'est pas gauréte de le faire.
B.T.W., vous ne synchronisez pas la variable i>, vous synchronisez sur l'objet auquel la variable se réfère. C'est une distinction importante car certaines personnes ont commis l'erreur de ne pas realiznig que la variable peut se référer à des objets différents à des moments différents, et certains ont commis l'erreur de ne pas se rendre compte que le même objet peut être référencé par plus d'une variable.
Ce code ressemble plus à un code de test qu'un cas réel, mais si vous souhaitez synchroniser sur une sécurité sans verrouillage, mais à thread-coffre-fort, Number , vous pouvez utiliser un AtomicInteger .
@jamesLarge: Je comprends ce que vous dites. Je n'étais pas précis sur cela parce que mon problème s'est concentré sur un autre point. Quoi qu'il en soit, merci. :)
@ Jean-FrançoisAvard: Oui, c'est un code de test, aucune pertinence pour de vrais projets. Juste en train de vérifier. Oui, atomicinteger, je sais que. Merci. :)
@ Jean-François: Pour clarifier, Atomicinteger est plus une alternative au verrouillage, ce n'est pas quelque chose que vous devez utiliser comme une serrure.
@Nathanhughes true.
Dans ce cas particulier, les deux threads se synchronisent sur la même instance code> entier code>, il convient de souligner qu'il n'y a rien de mal avec deux threads apparemment en cours d'exécution l'une après l'autre. Si deux threads ne se synchronisent pas, ils n'ont aucune relation de synchronisation, pas même une garantie de fonctionnement parallèle. Il apparaît donc de fonctionner entièrement après une autre, est un résultat entièrement plausible surtout i> pour des threads courts comme la question de la question.