本章内容
- 线程通信
- 为什么处理线程之间的通信
- 如何保证线程间通信有效的利用资源
- 什么是等待唤醒机制
- 等待唤醒中的方法
线程间通信
概念:
多个线程在处理同一个资源的时候,处理的的动作(线程的任务)却不相同。
比如说:
线程A用来生产娃哈哈,线程B用来消费娃哈哈,这时娃哈哈就可以理解成同一资源,线程A和线程B处理的动作不一样,一个是生产,一个是消费,那么线程A和线程B之间就存在线程通信问题。
为什么要处理线程之间的通信?
多个线程并发执行,在默认情况下,CPU是随机切换线程的,当我们需要多个线程共同完成一个任务时,并且我们希望他们有规律的执行,那么多个线程之间都需要一些协调通信,以此来帮助我们达到多线程共同操作同一份数据。
如何保证线程间通信有效的利用资源?
多个线程之间在处理同一个资源的时候,任务并不相同。需要线程通信来帮助我们解决线程之间对同一个变量的使用或者操作,就是多个线程在操作同一份数据时,为了避免对同一共享变量的争夺,也就是我们需要通过一定的手段使各个线程有效的利用资源。而这个手段就是等待唤醒机制。
什么是等待唤醒机制?
这是多个线程之间的一种协作机制,就是一个线程进行了规定操作后,就进入到了等待状态(wait方法),等待其他线程执行完他们的指定代码后,再将其唤醒(notify方法)。在有多个线程进行等待时,如果需要,可以使用notifyAll方法来唤醒所有的等待线程。
wait/notify就是线程之间的一种协作机制
等待唤醒之间的方法
等待唤醒机制就是用来解决线程间通信问题的,可以使用到的方法有以下三个:
- wait()线程不再活动,不再参与调度,进入到wait set中,因此不会浪费CPU资源,也不会去竞争锁,这里的线程状态就是WAITING状态,还要等着别的线程执行一个特别的动作(唤醒通知notify)在这个对象上等待的线程从wait set中释放出来,重新进入到调度队列中。
- notify()选取所通知对象的wait set中的一个线程释放。
- notifyAll()释放所通知对象的wait set中的全部线程。
备注: 哪怕通知了一个等待进程,被通知的线程也不能立即恢复执行状态,因为他当初中断的地方是在同步块中,而此刻他已经不持有锁了,所以他需要再次尝试获取锁(很可能面临着其他线程的竞争),成功后才能在当初调用wait方法之后的地方恢复执行。
总结:
如果能获取到锁,线程就从WAITING状态转变成RUNNABLE状态,否则从wait set中,又进入set中,线程就从WAITING状态转变成BLOCKED状态。
调用wait和notify的注意细节:
- wait方法与notify方法必须由同一个锁对象调用,因为,对应的锁对象可以通过notify唤醒使用同一个锁对象调用的wait方法
- wait方法和notify方法时属于Object类的方法。因为锁对象可以是任意对象。而任意对象的所属类都是继承了Object类。
- wait方法与notify方法都必须在同步代码块或者是同步方法中使用。因为必须通过锁对象调用这两个非来实现线程通信