Java wait()和await() notify()和signal() notifyAll()和signalAll()了解和区别

Java wait()和await() notify()和signal() notifyAll()和signalAll()了解和区别


wait()、notify()和notifyAll()一般是跟synchronized配合一起使用,这些方法都是Object类提供的。当线程重wait()状态下被唤醒,wait()在被唤醒后还需要重新去获取锁,此时它重新请求锁时并没有具备任何特殊的优先级,要与任何其他尝试进入同步代码块的线程一起去竞争获取锁,如果获取锁失败的话,会继续停留在当前的wait()方法状态下。所以wait方法继续执行时,一般会先通过一个条件判断,所以一般是在一个循环中去调用wait()方法。例如:

pubic syncronized T get() throws InterruptedException{
     while(isEmpty){
         wait();
     }
     T t = doGet();
     notifyAll();
     return t;
}

由于多个线程可以基于不同的条件在同一个条件队列中等待,所以一般是条用notifyAll(),避免造成消息的丢失。因为调用notify()只会唤醒一个线程,但是这个线程可能并不能从满足条件,这个时候系统其它线程满足条件会一直等待并无法被唤醒,这是一个非常危险的操作。所以一定要使用notifyAll()。

那么什么情况下使用notify()呢?

当满足(1)所有线程的wait()前置判断条件只有一个并且都是一样的(2)单进单出,每次通知发出后,这个条件下最多只有一个线程可以去执行。


Condition类的await()、signal()和signalAll(),一般是配合Lock一起使用,是显式的线程间协调同步操作类。每个Lock中可以有多个Condition,如notEmpty、notFull等。这些方法都是在某个具体的Condition条件队列中调用,唤醒的时候也是类似,使用对应的Condition来唤醒一个或者多个等待的线程。和wait()、notify()类似,使用这些方法时也需要先通过Lock获取锁,await()方法同样会释放锁,并挂起当前线程,等待被通知唤醒去重新竞争锁。


怎么选择?

一般情况下使用Object提供的3种方法就已经可以很好的实现线程间的协作。

当Lock锁使用公平模式的时候,可以使用Condition的signal(),线程会按照FIFO的顺序冲await()中唤醒。当每个锁上有多个等待条件时,可以优先使用Condition,这样可以具体一个Condition控制一个条件等待。


猜你喜欢

转载自blog.csdn.net/codingtu/article/details/78431066