写于:2019-12-01

# 线程通讯概念

与网络通讯等进程间通信方式不一样,线程间通讯又称为进程内通信,多个线程实现互斥访问共享资源时会互相发送信号或等待信号,比如线程等待数据到来的通知,线程收到变量改变的信号灯。

# JAVA 原生 API

# 1、Object.wait:阻塞当前线程

# wait 方法详细信息

  • a、上述三个重载 wait 方法,都表示将当前调用该方法的线程加入到 wait set 中。 wait():等价于 wait(0) ,表示当前阻塞永不超时。 wait(long) 和 wait(long ,int):表示阻塞当前线程一定时间,时间到了自动唤醒阻塞的线程。

  • b、被 wait 阻塞的线程,只有其他线程调用 Object.notify 或者 Object.notifyAll 时会被唤醒,或者阻塞时间到达 timeout 时间自动唤醒

  • c、wait 方法必须拥有该对象的 monitor ,也就是 wait 方法必须在同步方法中使用。

  • d、当前线程执行了该对象的 wait 方法之后,将会放弃对该 monitor 的所有权并进入与该对象关联的 wait set 中,也即是说一旦线程执行了某个 object 的 wait 方法之后,他就会释放该对象 monitor 的所有权,其他线程也有机会继续争抢该 monitor 的所有权。

小贴士:wati set

在虚拟机规范中存在一个 wait set 的概念,对于 wait set 的结构和规范 JDK 官方没有给出明确的定义,不同 JDK 厂家存在不同的差异,不管何种实现方式,都有如下特点:

a、所有的对象都会有一个 wait set ,用来存放调用了该对象wait方法之后进入 block 状态的线程。

b、线程被 notify 之后,不一定立即得到执行

c、线程从 wait set 中被唤醒顺序不一定是 FIFO

d、线程被唤醒之后需要重新获取锁

e、wait 方法之后线程进入到该对象 monitor 关联的 wait set 中,并释放 monitor 的所有权。

# wait 方法使用注意事项

  • a、wait 方法是可中断方法,当线程调用 wait 进入阻塞状态时,能够通过其他线程使用 interrupt 方法进行打断。 interrupt 相关解释

  • b、wait 方法必须在同步方法中使用,因为执行 wait 的前提条件是必须持有同步方法的 monitor 的所有权。

  • c、通过 notify 、notifyAll 或者中断 的方式能够唤醒 wait 中的线程。

# 2、Object.notify 和 Object.notifyAll:唤醒被wait阻塞的线程

通过 JDK DOC 说明能知道 notify 和 notifyAll 的区别。

  • notify 只会唤醒 wait set 中休息的一个线程
  • notifyAll 会唤醒 wait set 中休息的所有线程,多个线程仍需要争抢 monitor 的所有权。

如图:

精彩内容推送,请关注公众号!
最近更新时间: 5/4/2020, 8:05:42 PM