2017-05-13 59 views
0

为什么在开始时立即陷入死锁 - 它打印出一行然后冻结(建议编辑之后)?
这可能是因为第一个线程在开始等待之前未命中通知触发器。
分辨率是多少?初始化时出现死锁

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

布尔值不是引用,它们是值。你在内部类中本地设置b,但不通过threadTwo类,所以b在其他类中永远不会改变,看起来像?另外,你不需要同步布尔值,它们已经是原子的了(你的两个线程之间的通信不存在) –

+0

请尊重Java命名约定,类应该以大写字母开头。你能解释代码实际上做了什么吗?此外,你应该尝试缩小你的代码库到必要的部分。请不要这么做'布尔b =新布尔(假);'除非你有一个真正的好理由。一个“正常的”布尔值就足够了,你可以用'synchronized(this)'或'synchronized(i)'代替。 – Turing85

+1

@BiepbotVonStirling a)OP使用'布尔'而不是'布尔',这是一个区别,b)'synchronized(...)'有一些其他的效果。它实际上同步整个块,不仅访问同步变量,而且也不可能在Java中的基本变量上“同步(...)”。由于Java中的所有变量都是原语或引用,因此除了'double'和'long'之外,对所有变量的访问都是原子的。 – Turing85

回答

2

问题是b.wait()firstThread。 这个变量b决不会从secondThread得到通知,因为secondThread在检查if(b==true)时失败并立即返回。

但也知道这样一个事实,即通过变量b同步是非常糟糕的,因为报表 b=false;b=true;被分配新的实例变量,因此firstThreadsecondThread失去了联系。

+0

此外,请注意[Java中的布尔对象是不可变的](http://stackoverflow.com/questions/15194226/why-wrapper-class-like-boolean-in-java-is-immutable)。 –

0

如果我正确地猜测了代码的意图,那么就有不必要的同步和等待通知。试试这个:

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(); 

    } 
}