2016-06-10 2 views
-1

La condition de concurrence se produit, même si le bloc de code appelant est synchronisé. À la réflexion, il semble que ce soit un problème de verrouillage. S'il vous plaît, consultez le bloc de code simple suivant (code mieux l'expliquer) -Fil Java: condition de concurrence vs synchronisation

class CriticalSectionTest { 

    public void initWithSync() { 
     final CriticalSection cSection = new CriticalSection(); 

     Thread threadA = new Thread(new Runnable() { 
      @Override public void run() { 
       synchronized (cSection) { 
        cSection.add(2); 
        System.out.println(
          "Value after adding from thread-A: " + cSection.getCount()); 
       } 
      } 
     }); 

     Thread threadB = new Thread(new Runnable() { 
      @Override public void run() { 
       synchronized (cSection) { 
        cSection.add(3); 
        System.out.println(
          "Value after adding from thread-B: " + cSection.getCount()); 
       } 
      } 
     }); 

     threadA.start(); 
     threadB.start(); 

     //Desired output: 
     //A: 2 
     //B: 5 
    } 
} 

class CriticalSection { 
    private long count = 0; 

    public void add(long value) { 
     /* This method was not made synchronized, intentionally as its done in caller class 
     */ 
     this.count = this.count + value; 
    } 

    public long getCount() { 
     return count; 
    } 
} 

sur plusieurs pistes, il affiche les sorties suivantes: -

Ce n'est pas correct

Value after adding from thread-B: 3 
Value after adding from thread-A: 5 

Il semble correct

Value after adding from thread-A: 2 
Value after adding from thread-B: 5 

Une explication? ou est-ce que je manque des bases?

+3

La synchronisation ne détermine pas l'ordre d'exécution. Cela garantit simplement que les threads n'exécutent pas le code en même temps. Si vous souhaitez que le code s'exécute dans un ordre particulier et séquentiellement, n'utilisez pas plusieurs threads. –

+1

Une autre façon de dire ce que Andy Yassin a déjà dit ici: La synchronisation est _not_ destinée à empêcher les courses de données. Il est destiné à empêcher les courses de données de faire _harm_. Si votre programme est si fortement synchronisé qu'aucune course de données n'est possible, alors vous feriez mieux de le faire en un seul thread. –

Répondre

3

La synchronisation ne détermine pas l'ordre d'exécution. Cela garantit simplement que les threads n'exécutent pas le code en même temps. L'appel Thread.start() n'appelle pas immédiatement Thread.run(); il demande simplement à l'ordonnanceur de thread de l'exécuter à un moment donné dans le futur. L'explication du comportement que vous décrivez est que le planificateur de thread peut commencer à exécuter le thread B avant le thread A parfois. C'est le comportement attendu.

Si vous voulez que le code s'exécute dans un ordre particulier et séquentiellement, il est beaucoup plus facile de tout faire dans un seul thread.

2

Rien n'est sûr sur l'ordre de début de chaque thread. Main fil commencera les fils l'un après l'autre, mais rien empêche les éléments suivants:

THREAD A : START 
THREAD B : START 
THREAD A : WAIT 
THREAD B : RUN 
THREAD A : RUN 
THREAD A : STOP 
THREAD B : STOP 

threadB pourrait parfois commencer le traitement avant threadA et c'est ce que vous faites face en ce moment.