Je veux ajouter seulement deux nombres en utilisant deux fils, mais je n'ai pas compris où je me suis trompé.
Ma sortie est fausse.Et je sais que le problème est avec synchronisé mais pas capable de résoudre.
import java.io.*;
class GFG {
public static void main (String[] args) throws InterruptedException {
final Addition a=new Addition();
Thread t1 = new Thread(new Runnable()
{
public void run(){
try {
a.add(1,10);
} catch(Exception e) {
}
}
});
Thread t2 = new Thread(new Runnable()
{
public void run(){
try {
a.add(1,4);
} catch(Exception e) {
}
}
});
t1.start();
t2.start();
t1.join();
t2.join();
}
public static class Addition{
int a, b;
int sum=0;
public void add(int a, int b) throws InterruptedException{
synchronized(this){
for (int i=a;i<=b;i++){
sum=sum+i;
Thread.sleep(1000);
}
System.out.println("Sum="+sum);
}
}
}
}
Production:
Sum=55
Sum=65
Et en voyant la sortie, je peux dire que ... Après avoir terminé la tâche de THREAD t1, THREAD t2 ajoute son résultat au t1 ... ??
4 réponses
Le problème réel - outre que le code est manifestement trompeur exprès - est que sum
est un membre de classe de Addition
. Comme vous utilisez la même instance de Addition
dans les deux threads, l'état de la somme est partagé entre les threads. C'est-à-dire que le deuxième thread ne commencera pas à se résumer avec 0
mais avec le résultat de l'ajout précédent 55
. Cela conduit à la sortie observée.
Si vous remplacez Addition
par ce qui suit, le programme se comportera comme prévu.
public static class Addition {
int a, b;
public void add(int a, int b) throws InterruptedException {
int sum = 0;
synchronized (this) {
for (int i = a; i <= b; i++) {
sum = sum + i;
Thread.sleep(1000);
}
System.out.println("Sum=" + sum);
}
}
}
Cela a été conçu par quelqu'un pour être délibérément trompeur (peut-être appartient-il à un débordement d'énigmes?). L'indentation ne correspond pas aux accolades.
Vous pouvez dire que "sum" ne sera initialisé à zéro qu'une seule fois et jamais réinitialisé à zéro car l'addition n'est construite qu'une seule fois (la nouvelle addition ne se produit qu'une seule fois).
Si vous voulez que l'objet Addition fonctionne indépendamment, définissez certains sur zéro dans le fichier synchronisé.
Je déteste un peu avoir répondu à cela parce que c'est évidemment un type de puzzle / devoirs construit, mais vous pouvez avoir celui-ci comme cadeau je suppose
- Les deux threads utilisent la même instance de la classe
Addition
. - L'instance unique de la classe
Addition
a la variablesum
qui est partagée entre les threads t1 et t2. - Selon que chaque thread est en cours d'exécution, ils modifient la valeur de
sum
et le résultat est fusionné.
J'ai exécuté votre programme et apporté des modifications pour ajouter des journaux, comme vous pouvez le voir:
public static class Addition{
int a, b;
private int sum=0;
public void add(int a, int b, int id) throws InterruptedException{
System.out.println("INIT ADD t:[" + id + "]");
synchronized(this){
for (int i=a;i<=b;i++){
System.out.println("Sum Before t:[" + id + "] i:[" + i + "]=" + sum);
sum=sum + i;
System.out.println("Sum After t:[" + id + "] i:[" + i + "]=" + sum);
Thread.sleep(1000);
}
}
System.out.println("Sum t:[" + id + "]=" + sum);
}
}
Le journal confirme que je vous l'ai dit, la somme variable est affectée à chaque fois par chaque bande de roulement. Voici le journal:
INIT ADD t:[1]
Sum Before t:[1] i:[1]=0
INIT ADD t:[2]
Sum After t:[1] i:[1]=1
Sum Before t:[1] i:[2]=1
Sum After t:[1] i:[2]=3
Sum Before t:[1] i:[3]=3
Sum After t:[1] i:[3]=6
Sum Before t:[1] i:[4]=6
Sum After t:[1] i:[4]=10
Sum Before t:[1] i:[5]=10
Sum After t:[1] i:[5]=15
Sum Before t:[1] i:[6]=15
Sum After t:[1] i:[6]=21
Sum Before t:[1] i:[7]=21
Sum After t:[1] i:[7]=28
Sum Before t:[1] i:[8]=28
Sum After t:[1] i:[8]=36
Sum Before t:[1] i:[9]=36
Sum After t:[1] i:[9]=45
Sum Before t:[1] i:[10]=45
Sum After t:[1] i:[10]=55
Sum t:[1]=55
Sum Before t:[2] i:[1]=55
Sum After t:[2] i:[1]=56
Sum Before t:[2] i:[2]=56
Sum After t:[2] i:[2]=58
Sum Before t:[2] i:[3]=58
Sum After t:[2] i:[3]=61
Sum Before t:[2] i:[4]=61
Sum After t:[2] i:[4]=65
Sum t:[2]=65
Lorsque vous synchronisez le bloc for
, le deuxième thread (t2
) commence à ajouter et à stocker le résultat dans sum
, mais sum
a le résultat de t1
( 55) au début de for
.
Alors, selon ce journal, quel est le comportement que vous souhaitez obtenir?
Vous utilisez la même instance de Addition: "a"
et bien que les Addition's
variables globales "a" and "b"
soient masquées, mais "sum"
ne l'est pas.
De nouvelles questions
java
Java est un langage de programmation de haut niveau. Utilisez cette balise lorsque vous rencontrez des problèmes pour utiliser ou comprendre la langue elle-même. Cette balise est rarement utilisée seule et est le plus souvent utilisée en conjonction avec [spring], [spring-boot], [jakarta-ee], [android], [javafx], [hadoop], [gradle] et [maven].