java wait notifyall_Java中的wait/notify/notifyAll

方法

java.lang.Object

public final native void wait() throws InterruptedException;

public final native void wait(long millis, int nanos) throws InterruptedException;

public final void wait(long millis) throws InterruptedException {

wait(millis, 0);

}

public final native void notify();

public final native void notifyAll();

wait():使调用该方法的线程释放锁,从运行状态退出,进入等待队列,直到被唤醒。

wait(long timeout):等待一段时间是否有线程唤醒锁,如果没有,超时自动唤醒。

wait(long timeout, int nanos):等待唤醒时间纳秒级别。

notify():随机唤醒等待队列中的等待同一个锁的一个线程,使这个线程退出等待队列,进入可运行状态。

notifyAll():唤醒所有等待同样锁的所有线程,从等待队列中退出,进入可运行状态。

注意点

在调用wait或者notify之前,必须获得该对象的对象锁,即,只能在同步方法中调用;

执行完wait之后释放对象锁,所以其他线程可以获得执行机会,才能唤醒;

执行notify之后,不会立即退出让wait的线程执行,必须要先把同步块中的程序执行完,退出同步块,才会释放锁,让等待线程执行;

notify每次通知一个线程,多次调用通知线程数增加,可将wait线程全部唤醒。

原理

每个对象都有个monitor,初始是0,执行完synchronized值就是1。

wait/notify需要在获得monitor的线程中才可以执行。

所以,wait/notify需要在synchronized中执行。

其中,wait又会释放掉锁,破坏掉同步。

跟synchronized关系

synchronized代码块生成的字节码,被monitorenter和monitorexit包围,持有对象的monitor;

线程执行wait/notify方法时,必须持有对象的monitor;

所以,wait/notify方法在synchronized同步块中执行,就持有了对象的锁。

互斥和协同

Java语言的同步机制在底层实现上只有两种方式:互斥和协同。

互斥:即synchronized内置锁。

协同:即内置条件队列,wait/notify/notifyAll。

条件队列中是处于等待状态的线程,等待特定条件为真。每个Java对象都可以作为一个锁,同样每个Java对象都可以作为一个条件队列。通过wait/notify/notifyAll来操作条件队列。

可以理解为:有一个队列,o.wait()就push进去,o.notify()就pull出来。

要调用条件队列的任何一个方法,都必须要获得对象上的锁。

线程是用来工作的,不应该处于等待状态,处于等待状态的条件队列中的线程,一定是执行不下去的。

在while中等待

while(condition is not true) {

lock.wait()

}

解释:两个消费者线程c1和c2,逻辑都是,判断资源是否为空,是就wait,否就消费一个;某个时刻,两个线程都进入等待队列,然后生产者生产了一个资源,并执行notifyAll,唤醒c1和c2都进入锁池,c1先获取锁,执行完消费掉资源,然后释放锁,此时,如果c2获得锁,如果是if逻辑,那么就会进入消费代码,但是资源已经被c1消费掉了,可能抛出异常。如果是while逻辑,则不会进入消费代码,而是继续等待。

在一般情况下,总应该调用notifyAll唤醒所有需要被唤醒的线程。可能会唤醒其他一些线程,但这不影响程序的正确性,这些线程醒来之后,会检查他们正在等待的条件(循环检测),如果发现条件不满足,就会继续等待

79b7e4626169dcc7f36833c35b43069b.png

显示锁和显示条件队列

显示锁:Lock,对应内置锁synchronized

显示条件队列:Condition,对应内置条件队列,对应方法是await, signal, signalAll

问题

notifyAll唤醒所有线程,但不是所有线程都能执行,必须要等待对象锁被释放,获取锁之后才能执行。可以说,notifyAll让线程进入锁池。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值