2010-11-28 64 views
2

主题1:简单的Java并发问题

if(!conditionFullfiled) this.wait(); 

线程2:

if(conditionFullfiled) thread1.notify(); 

我想从线程2唤醒线程1,当一些条件fullfiled。但是,当thread1.notify()被称为if(!conditionFullfiled) ***HERE*** this.wait();时,是不是有问题?

回答

3

要做obj.wait()obj.notify(),您需要拥有您要等待/通知对象的监视器。在你的代码中,你可能不需要thread1.notify()。例如:

Object someSharedObject = ... 

线程1:

synchronized(someSharedObject) { 
    // while NOT if for spurious wake ups. 
    while(!conditionFullfiled) someSharedObject.wait(); 
    } 

线程2:

synchronized(someSharedObject) { 
    if(conditionFullfiled) someSharedObject.notify(); // this wakes thread1 
    } 

的​​锁定时someSharedObject(可以是this),这意味着这两个线程将永远不会发生冲突。 .wait()释放当前保持的监视器,因此当Thread1正在等待时,线程2不会被阻塞。

编辑:我学到了一些关于虚假唤醒的知识。 .wait()必须在while循环中完成 - if是不够的。 Why do threads spontaneously awake from wait()?。谢谢Enno Shioji教我。

编辑:澄清.wait()版本监测。

+0

`if`应该`while`被替换应付虚假的起床。 – 2010-11-28 12:38:03

0

你用什么对象作为“this”?如果调用wait()的线程1对象上,你表现出的语句都被包裹在这样的循环:

new Runnable() { 
    synchronized (thread1) { 
     thread1.wait() 
    } 
} 

那么你的代码将工作,只要你想。 (当条件为false时,第一个线程将停止,否则工作)。 诀窍是线程对象上的交互是同步的,因此一个线程不能在其他人使用该对象时中断。

编辑: 如果您不是在线程上进行同步,而是在某个其他对象(您可以简单地创建纯对象以提供锁定)上进行同步,那将会更好。

0

因为等待释放对象锁定(在这种情况下)完全没问题。

这是防止等待/通知条件的最佳做法,以避免虚假的唤醒。

3

这里有2个问题。

  1. 你不应该在线程对象本身上调用wait()和notify()。更好的方法是使用特殊的锁定对象,例如

    private Object lock = new Object(); ...... lock.wait();

  2. 接下来的问题是,必须调用二者wait()和通知到synchornized块,即

    syncronized(锁){// 一些代码 lock.wait(); }

然后在代码中的其他地方说:

syncronized(lock) { 
    lock.notify(); // this line will cause the wait to terminate and the first thread to continue. 
} 

这是方便在一类本地化既wait()notify()包装方法,使他们有机会获得锁定对象。

欲了解更多信息,请阅读 http://download.oracle.com/javase/6/docs/api/ http://download.oracle.com/javase/6/docs/api/java/lang/Thread.html