线程等待通知 linux,多线程之--等待与通知

wait/notify

等待线程和通知线程是同步在同一对象之上的两种线程

使用过程

//等待

synchronized(object){

//保护条件不成立时,当前线程暂停,进入等待集 while(!保护条件){ object.wait(); } doSomething(); } //唤醒 synchronized(object){ //更新等待线程保护条件涉及的共享变量 updateSharedState(); object.notify(); }

内部实现

Java虚拟机会给每个对象维护一个入口集EntrySet用于存储申请该对象内部锁的线程,和等待集WaitSet用于存储该对象上的等待线程;

线程B获取锁

保护条件不满足,线程B暂停,并释放锁(原子操作),将当前线程的引用存入该方法所属对象的等待集中

线程A申请锁

线程A获取锁

线程A更新保护条件

保护条件满足,唤醒等待集中任意线程

线程B被唤醒但仍留在等待集中,尝试获取锁,成功获取锁,等待集移除线程B,Object.wait()调用返回

//wait伪代码实现

pulic void wait(){

if(Thread.holdLock(this)){ throw new IllegalMonitorStateException(); } if(waitSet.contains(Thread.currentThread())){ addToWaitSet(Thread.currentThread()); } //原子操作 atomic { releaseLock(this); //暂停当前线程 等待唤醒 block(Thread.currentThread()); } //被唤醒后 acquireLock(this); removeFromWaitSet(Thread.currentThread()); return; }

例子:监控服务/等待超时控制/Thread.join实现

wait/notify问题

问题

wait(long)不能区分其返回是否因等待超时而导致的问题

解决

juc包下的Condition类的awaitUtil(Date)方法(todo实现)

过早唤醒

问题

因为一个对象只维护一个等待集,当在这个对象中的一个保护条件A被更新且成立时,调用notifyAll将会唤醒所有等待线程,这时使用其他保护条件B的等待线程甲也会被唤醒,发现自己保护条件不成立,只能继续等待。

解决

juc包下的Condition类的await方法

信号丢失

问题

保护条件成立判断和wait调用没有放在一个临界区内的循环里(todo)

问题

notify唤醒不考虑任何保护条件,即notify没有成功唤醒当前等待条件上的等待线程,可能唤醒了其他保护条件的线程或一个都没唤醒,需换成notifyAll

欺骗性唤醒

问题

等待线程没有在notify/notifyAll的情况下因操作系统导致被唤醒,导致过早唤醒,需要保护条件成立判断和wait调用放在一个临界区内的循环里

导致较多的上下文切换

原因

锁的申请与释放

等待线程从暂停到被唤醒

与申请锁的Runnable线程争取相应的内部锁

过早唤醒的等待线程

解决

保证程序正确性的前提下,notify代替notifyAll

通知线程执行完notify/notifyAll后尽早释放锁,导致被唤醒线程需要多次申请锁而被暂停(todo)

notify/notifyAll的选用

优点

缺点

适用

notify

信号丢失

同质多等待线程

notifyAll

正确性

过早唤醒

具体案例

Thread.join()是一个同步方法,其内部就是使用wait/notify来实现,等待目标线程执行结束后再继续执行;等待线程在目标线程未结束时调用wait来暂停自己,虚拟机会在目标线程的run方法运行结束后执行notifyAll。(同步的概念是什么todo)

Condition

是wait/notify的替代品,await方法类似于wait,signal方法类似于notify,signalAll类似于notifyAll;由显示锁Lock创建,并要求其执行线程持有创建该Condition实例的显式锁。可用于解决wait(long)无法区分是因为超时等待还是被通知而返回,及过早唤醒问题。 Condition实例也被称为条件变量,内部维护一个存储等待线程的队列。

使用过程

class ConditionTest{

private final Lock lock = new ReentrantLock(); private final Condition condition = lock.newCondition(); public void awaitFunc() throws Exception{ lock.lock(); try{ while(!保护条件){ condition.await(); } doSomething(); }finally{ lock.unlock(); } } public void signalFunc(){ lock.lock(); try{ updateState(); condition.signal(); }finally{ lock.unlock(); } } }

实现原理

建立保护条件与条件变量之间的对应关系,让不同保护条件的等待线程调用对应条件变量的await方法实现等待,signal同理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值