2014-11-08 44 views
3

我不熟悉Java并发。我有一个简单的对象与3个方法,每个对应的代码运行3个不同的线程。为什么notifyAll()语句在这种情况下不会释放其他两个线程中的等待?为什么notifyAll()在这种简单情况下不能恢复其他线程?

public class Main { 
static class Obj { 
     synchronized void t1() { 
      System.out.println("T1 ran"); 
      try { 
       Thread.sleep(1000); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
      notifyAll(); 
     } 
    synchronized void t2() { 
     try { 
      wait(); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
     System.out.println("T2 ran"); 
    } 
    synchronized void t3() { 
     try { 
      wait(); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
     System.out.println("T3 ran"); 
    } 
} 

public static void main(String[] args) { 
    final Obj o = new Obj(); 
    new Thread(new Runnable() { 
     @Override 
     public void run() { 
      o.t1(); 
     } 
    }).start(); 
    new Thread(new Runnable() { 
     @Override 
     public void run() { 
      o.t2(); 
     } 
    }).start(); 
    new Thread(new Runnable() { 
     @Override 
     public void run() { 
      o.t3(); 
     } 
    }).start(); 
}} 

我预计: T1跑 ~~停顿1秒~~ T2跑 T3跑

我: T1跑

回答

6

Thread.sleep不释放或在wait的方式做放松任何锁,所以同步仍处于完整的效果和其他线程将不会被允许在睡眠期间进入他们的方法。

如果更换

Thread.sleep(1000); 

wait(1000); 

其他线程将被允许拍摄相同的锁定,输入方法,开始等待,并为您预期的样品将工作。

+0

真棒谢谢! – 2014-11-08 21:29:31

+0

@其他人:我只用包含方法't1,t2,t3'(Obj1,Obj2,Obj3)的3个不同的“对象”测试源代码 - 结果是相同的。为什么在Obj1上的同步方法会阻止不同的线程分别访问'Obj2.t2'和'Obj3.t3'? – dognose 2014-11-08 21:39:58

+0

啊没关系 - 其他方法已经被发现,但是。 'notifyAll'没有影响,然后:-)所以其他对象线程正在等待,直到黎明:) – dognose 2014-11-08 21:47:16

3

你的三种方法是​​在同实例。并且Thread#sleep(..)不会释放由​​获取的锁定。因此,执行t1的线程获得锁,休眠一秒钟,唤醒,呼叫notifyAll()并完成。

然后你的两个其他线程在执行时会轮到一个回合,然后调用wait()。但是没有什么可以通知他们的,所以你的应用程序会阻止。

你有一个竞赛条件。改变你开始线程的顺序或者像你有足够的时间运行它,你可能会看到不同的行为。

+0

我没有考虑到让t1睡1秒? – 2014-11-08 21:18:40

+0

@ db-user我会检讨。错过了。 – 2014-11-08 21:19:57

+0

@ db-user'sleep'不释放'synchronized'锁。所有线程都将等待该方法调用完成。 – 2014-11-08 21:21:27

3

如果我是正确的,方法t2和t3的线程不能进入方法,因为线程t1锁定对象的整个时间,就像它是一个同步方法。而到了时间T2和T3实际运行notifyAll的()已经发生了,所以他们永远等待:(

你应该尝试启动T2和T3,再T1。

前面已经指出。的Thread.sleep (),因为它被标记的同步不会释放任何锁定或监视器所以该方法不能被其他线程进入:Thread.sleep()

相关问题