简单的Java并发问题

时间:2010-11-28 12:04:44

标签: java concurrency synchronization

主题1:

if(!conditionFullfiled) this.wait();

主题2:

if(conditionFullfiled) thread1.notify();

我想从线程2中唤醒线程1,当某些条件已满。但是,当thread1.notify()被调用if(!conditionFullfiled) ***HERE*** this.wait();时,是不是有问题?

4 个答案:

答案 0 :(得分: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
   }

synchronized锁定在someSharedObject上(可以是this),这意味着两个线程永远不会发生冲突。 .wait()释放当前持有的监视器,因此当Thread1等待时不会阻止Thread2。

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

修改:澄清.wait()版本监控。

答案 1 :(得分:3)

这里有2个问题。

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

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

  2. 下一个问题是你必须同时调用wait()并通知同步块,即

    同步(锁定){     //一些代码     lock.wait(); }

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

    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

答案 2 :(得分:0)

你用什么对象作为“这个”?如果你在thread1对象上调用wait(),你所显示的两个语句都包含在这样的循环中:

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

然后您的代码将按您的意愿运行。 (当条件为假时,第一个线程将停止,否则将工作)。 诀窍是线程对象上的交互是同步的,因此一个线程不能中断而其他线程正在使用该对象。

编辑: 如果你不在线程上同步,而是在其他一些对象上同步(你可以简单地创建纯对象来提供锁定),那就更好了。

答案 3 :(得分:0)

完全没问题,因为等待释放对象锁定(如果是这样)。

保护while块中的等待/通知条件是最佳做法 - 避免虚假唤醒。