2017-05-13 5 views
0

Warum kommt es sofort beim Start in einen Deadlock - es druckt eine Zeile und friert dann ein (nach den Edits empfohlen)?
Dies liegt wahrscheinlich daran, dass der erste Thread den Benachrichtigungstrigger verpasst, bevor er zu warten beginnt.
Was ist die Auflösung?Deadlock bei Initialisierung

public class threadTwo{ 
    AtomicInteger i=new AtomicInteger(0); 
    Boolean b=new Boolean(false); 

    class firstThread implements Runnable{ 
     AtomicInteger i; 
     Boolean b; 
     firstThread(AtomicInteger i,Boolean b){ 
      this.i=i; 
      this.b=b; 
     } 
     public void run(){ 
      while(true){ 
       synchronized(i){ 
        try{ 
         while(b==false) 
          i.wait(); 

         if(i.intValue()<30){ 
          i.incrementAndGet(); 
          System.out.println(Thread.currentThread().getId() + " - " + i.intValue()); 
         } 
         b=false; 
         i.notify(); 

        }catch(InterruptedException x){} 
       } 
      } 
     }  
    } 

    class secondThread implements Runnable{ 
     AtomicInteger i; 
     Boolean b; 
     secondThread(AtomicInteger i,Boolean b){ 
      this.i=i; 
      this.b=b; 
     } 
     public void run(){ 
      while(true){ 
       synchronized(i){ 
        try{ 
         while(b==true) 
           i.wait(); 

         if(i.intValue()<40){ 
          i.getAndAdd(2); 
          System.out.println(Thread.currentThread().getId() + " - " + i.intValue()); 
         } 
         b=true; 
         i.notify(); 

        }catch(InterruptedException x){} 
       } 
      } 
     }  
    } 

    void runThread(){ 
     Thread t1 = new Thread(new firstThread(i,b)); 
     Thread t2 = new Thread(new secondThread(i,b)); 
     t1.start(); 
     t2.start(); 
     try{ 
      t1.join(); 
      t2.join(); 
     }catch(Exception e){} 
     System.out.println("Result : " + i.intValue()); 
    } 

    public static void main(String[] args){ 
     new threadTwo().runThread(); 

    } 

} 
+0

Booleans sind keine Referenzen, sie sind Werte. Sie setzen b lokal in der inneren Klasse, aber nicht durch die threadTwo Klasse, also wird b in der anderen Klasse nie geändert, scheint es? Außerdem müssen Sie die booleschen Werte nicht synchronisieren, da diese bereits atomar sind (Ihre Kommunikation zwischen den beiden Threads ist nicht vorhanden). –

+0

Bitte beachten Sie die Java-Namenskonvention. Klassen sollten mit einem Großbuchstaben beginnen. Können Sie erklären, was der Code tatsächlich macht? Außerdem sollten Sie versuchen, Ihre Codebasis auf die erforderlichen Teile zu verkleinern. Und tu das bitte nicht 'Boolean b = new Boolean (false); 'es sei denn du hast einen WIRKLICH guten Grund. Ein "normales" 'boolean' ist ausreichend und Sie können stattdessen' synchronized (this) 'oder' synchronized (i) ''. – Turing85

+1

@BiepbotVonStirling a) OP benutzt 'Boolean', nicht' boolean', das ist ein Unterschied und b) 'synchronisiert (...)' hat einige andere Effekte. Es synchronisiert tatsächlich den gesamten Block, nicht nur den Zugriff auf die synchronisierte Variable und es ist unmöglich, auf eine primitive Variable in Java "zu synchronisieren". Da alle Variablen in Java entweder Primitive oder Referenzen sind, ist der Zugriff auf alle Variablen außer "double's" und "longs" garantiert atomar. – Turing85

Antwort

2

Das Problem ist b.wait() im firstThread. Diese Variable b wird nie von secondThread gemeldet, weil die secondThread die Prüfung if(b==true) nicht besteht und sofort zurückkehrt.

Aber auch der Tatsache bewusst sein, dass die Synchronisierung über die Variable b sehr schlecht, weil die Aussagen b=false; und b=true; zuweisen neue Instanzen auf die Variablen und daher firstThread und secondThread verlieren ihre Verbindung.

+0

Beachten Sie auch, dass [Boolesche Objekte in Java unveränderlich sind] (http://stackoverflow.com/questions/15194226/why-wrapper-class-like-boolean-in-java-isimmutable). –

0

Wenn ich die Absichten des Codes richtig erraten, dann gibt es unnötige Synchronisation und warte-notify. Versuchen Sie dies stattdessen:

public class MyThread 
{ 
    AtomicInteger i = new AtomicInteger(0); 
    Boolean b = new Boolean(false); 

    class FirstThread implements Runnable 
    { 
     AtomicInteger i; 
     Boolean b; 

     FirstThread(AtomicInteger i, Boolean b) 
     { 
      this.i = i; 
      this.b = b; 
     } 

     public void run() 
     { 
      while (i.intValue() < 30) 
      { 
       i.incrementAndGet(); 
       System.out.println(Thread.currentThread().getId() + " - " + i.intValue()); 
      } 
     } 
    } 

    class SecondThread implements Runnable 
    { 
     AtomicInteger i; 
     Boolean b; 

     SecondThread(AtomicInteger i, Boolean b) 
     { 
      this.i = i; 
      this.b = b; 
     } 

     public void run() 
     { 
      while (i.intValue() < 40) 
      { 
       i.getAndAdd(2); 
       System.out.println(Thread.currentThread().getId() + " - " + i.intValue()); 
      } 
     } 
    } 

    void runThread() 
    { 
     Thread t1 = new Thread(new FirstThread(i, b)); 
     Thread t2 = new Thread(new SecondThread(i, b)); 
     t1.start(); 
     try 
     { 
      t1.join(); 
     } 
     catch (InterruptedException exc) 
     { 
      exc.printStackTrace(); 
     } 
     t2.start(); 
     try 
     { 
      t2.join(); 
     } 
     catch (InterruptedException exc) 
     { 
      exc.printStackTrace(); 
     } 
     System.out.println("Result : " + i.intValue()); 
    } 

    public static void main(String[] args) 
    { 
     new MyThread().runThread(); 

    } 
} 
Verwandte Themen