wait notify等待唤醒机制------学习java并发编程之美笔记

线程通知与等待wait notify生产消费者模式
如果当前 队列没有空闲容量则会调用queued的wait()方法挂起当前线程,这里使用循环就是为了 避免上面说的虚假唤醒问题。假如当前线程被虚假唤醒了,但是队列还是没有空余容量, 那么当前线程还是会调用wait()方法把自己挂起。

生产线程

synchronized (queue) {
//消费队列满,则等待队列空闲
while (queue.size() == MAX_SIZE) (
try (
//挂起当前线程,并释放通过同步块获取的queue上的锁,
让消费者线程可以获取该锁,然后 获取队列里面的元素

queue.wait();
} catch (Exception ex) (
ex.printStackTrace();
)
}
//空闲则生成元素,并通知消费者线程
queue.add(ele);
queue.notifyAll();
}
}

消费者线程

synchronized (queue) {
〃消费队列为空
while (queue.size() == 0) {
try
//挂起当前线程,并释放通过同步块获取的queue上的锁,让生产者线程可以获取该锁,将生 产元素放入队列
queue.wait();

} catch (Exception ex) {
ex.printStackTrace();
 }
}
//消费元素并通知唤醒生产者线程
queue. take ();
queue.notifyAll();
 }
}

在如上代码中假如生产者线程A首先通过synchronized获取到了 queue上的锁,那么 后续所有企图生产元素的线程和消费线程将会在获取该监视器锁的地方被阻塞挂起。线程 A获取锁后发现当前队列已满会调用queue.wait()方法阻塞自己,然后释放获取的queue 上的锁,这里考虑下为何要释放该锁?如果不释放其他生产者线程和所有消费者线 程都己经被阻塞挂起,而线程A也被挂起,这就处于了死锁状态。这里线程A挂起自己 释放共享变量上的锁,就是为了打破死锁必要条件之一的持有并等待原则。线程A释放锁后,其他生产者线程和所有消费者线程中会有一个线程获取queue上的锁进而进入同步块,这就打破了死锁状态。需要注意的是,当前线程调用共享变量的wait()方法后只会释放当前共享变量的锁。

你可能感兴趣的:(java基础)