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 ... ??

-1
Gajendra Tiwari 15 nov. 2017 à 22:39

4 réponses

Meilleure réponse

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);
    }
  }
}
0
dpr 16 nov. 2017 à 16:44

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

0
Bill K 15 nov. 2017 à 20:00
  • Les deux threads utilisent la même instance de la classe Addition.
  • L'instance unique de la classe Addition a la variable sum 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?

0
Jorge Omar Medra 15 nov. 2017 à 21:06

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.

0
Khanna111 15 nov. 2017 à 20:00
47315896