multithreading状态依赖问题

我得到以下代码片段:

public class ThreadTest{ private static class Thread01 extends Thread{ private Thread02 _th2; public int foo = 0; public void setThrd02(Thread02 thrd2){ _th2 = thrd2; } public void run(){ try{ for(int i=0;i<10;i++) foo += i; synchronized(this){this.notify();}; synchronized(_th2){_th2.wait();}; System.out.print(" Foo: " + _th2.foo); }catch(InterruptedException ie){ ie.printStackTrace();} } } private static class Thread02 extends Thread{ private final Thread01 _th1; public int foo = 0; public Thread02(Thread01 th1){ _th1 = th1; } public void Run(){ try{ synchronized(_th1){_th1.wait();} foo = _th1.foo; for(int i=0;i<10;i++) foo += i; synchronized(this){this.notify();}; } catch(InterruptedException ie){ie.printStackTrace();} } } public static void main(){ Thread01 th1 = new Thread01(); Thread02 th2 = new Thread02(th1); th1.setThrd02(th2); th1.start(); th2.start(); th1.join(); th2.join(); } } 

我认为代码的假设和相应的目的就像th2先运行一样,通过调用_th1.wait()将其改为等待状态; 然后,th1计算foo并唤醒th2,th1进入等待状态; Th2从thread1读取foo并更新为110,然后唤醒th1和th2退出。 然后th1退出。

线程可能非常危险,因为线程1很可能首先运行而线程2将永远等待。

我不确定代码的任何其他潜在问题。

可以解决问题的一种可能方法是,例如在thread1中

公共类ThreadTest {

private static boolean updated = false; private static boolean finished = false;

private static Thread01扩展Thread {

public void Run(){//做计算while(已完成){wait(); } //输出结果}}

private static Thread02 extends Thread {public void run(){

while(false){wait(); }

foo = th1.foo; //做计算//通知线程1的类似机制}}

无法保证在您的主题中订购。 Thread01经过synchronized(this){this.notify();};足够了synchronized(this){this.notify();}; 在Thread02 synchronized(_th1){_th1.wait();}让两个线程无限期地等待。

注意:您在_th1和_th2上调用waitnotify这一事实无关紧要。 此处的线程将被视为任何其他对象。

@Alex已经指出了wait和notify没有按照代码期望的顺序调用的问题(+1)。 但是,由于这是一个面试问题,因此此代码还有其他一些问题:

  1. 糟糕的命名约定和代码格式,
  2. 公共现场存取器,
  3. 在Thread对象上同步(奇异),
  4. 捕获InterruptedException然后退出Thread,
  5. 没有exception处理,
  6. (个人偏好)不使用Java并发库。

我确定提出的问题是将你打结并弄清楚为什么并发性被破坏但是,恕我直言,那段代码是如此可怕,我甚至不会开始调试它 – 我只是扔掉它。

以下可以是更好的解决方案

 public class ThreadTest{ private static volatile boolean updated = false; private static volatile boolean finished = false; private static class Thread01 extends Thread{ private Thread02 _th2; public int foo = 0; public void setThread2(Thread02 th2){ _th2 = th2; } public void Run(){ for(int i=0;i<10;i++) foo += i; System.out.print(" thread1 calcualtion " + foo + "\n"); try{ updated = true; synchronized(this) {this.notify();}; synchronized(_th2){ while(!finished) _th2.wait(); System.out.print("Foo: " + _th2.foo ); } } catch(InterruptedException ie){ ie.printStackTrace(); } } } private static class Thread02 extends Thread{ private final Thread01 _th1; public int foo = 0; public Thread02(Thread01 th1){ _th1 = th1; } public void run(){ try{ synchronized(_th1){ while(!updated) _th1.wait(); foo = _th1.foo; } for(int i=0;i<10;i++) foo +=i; finished = true; synchronized(this){ this.notify();} }catch(InterruptedException ie){ ie.printStackTrace(); } } } public static void main(String[] args) { // TODO Auto-generated method stub Thread01 th1 = new Thread01(); Thread02 th2 = new Thread02(th1); th1.setThread2(th2); try{ th1.start(); th2.start(); th1.join(); th2.join(); }catch(InterruptedException ie){ ie.printStackTrace(); } }