浅析wait与synchronized

简介: 在Java语言中,Object作为顶级的父类中有一个wait()方法,我们都知道wait()跟notify()作为Java中的线程通信机制,但是你有没有想过:为什么wait方法是在Object中?它为什么不是在Thread中?

前言

在Java语言中,Object作为顶级的父类中有一个wait()方法,我们都知道wait()跟notify()作为Java中的线程通信机制,但是你有没有想过:为什么wait方法是在Object中?它为什么不是在Thread中?

生产者/消费者模型

生产者/消费者模型作为在Java中常见的多线程编程模型,其在分布式的系统也同样常见。它们大致的角色责任可以理解如下:生产者生产一批数据放到数据缓冲区中,然后重复生产过程。同样,消费者也在数据缓冲区消费这批数据,如下图。
image.png
通过上图,你可能会联想到几个问题:缓冲区如果满了生产者线程怎么办?缓冲区如果空了消费者线程怎么办?数据缓冲区的线程安全如何保证?那么我们可以尝试解答一下。

  • 数据缓冲区线程安全粗暴一点,直接加锁实现。
  • 数据缓冲区满了,要么生产者重试,等数据缓冲区有空位的时候在进行操作。又或者可以让生产者线程进行阻塞,等消费者消费处理完通知生产者可以操作了。
  • 数据缓冲区为空消费者跟上面也一样,可以重试获取,又或者可以让消费者线程进行阻塞,等生产者生产完通知消费者进行消费。
这里讨论生产者/消费者模型只是为了推导出双向通知的问题。具体的生产者/消费者模型的详细内容可以查阅一下相关资料,不涉及到本篇内容了,不在详细赘述。

如何进行双向通知?

wait()跟notify()不仅是同步工具,更重要的是它是作为Java中的线程通信机制的保障,如下译文所示,我们可以轻松的使用wait()跟notify()进行多个线程之间的“等待与唤醒”的操作,来实现生产者/消费者模型中的双向通知的问题。
image.png
image.png

为什么要使用synchronized?

从上文所述,wait()跟notify()必须要跟synchronized一起使用,那么为什么要一起使用呢?其实我们可以想一想,在两个线程之间,如果没有synchronized,在并发的情况下会出现什么样的问题,如下。
image.png
那么通过上图分析下来,最终造成的问题现象就是:数据缓冲区有数据存在,但是消费者线程一直在空挂起,导致线程A永远获取不到缓冲区的内容了。
而jvm也限制了这一点,如果在使用wait()的方法中,没有synchronized的话,在运行的时候会抛出IllegalMonitorStateException异常,这也很好解释,因为你都使用notify()方法了,那么肯定当前也会是一个多线程同步的环境,为了防止这种问题发生,只能限制这种开发方式了。

为什么wait方法是在Object中?

我们在使用synchronized实现了wait/notify的时候,通常都是A线程调用锁对象的wait方法,B线程调用锁对象的notify方法,所以该对象本身就需要同步。在两个线程之间如何通信?通信本身就需要"通信数据",而这个通信数据,就是这个"锁对象"。而这个对象本身就是不固定的,所以它可以是任意对象,所以它也只能在Object被定义了。还有就是在多个线程之间,在进入临界区本身就需要锁定等待的,线程与线程之间并不需要知道哪些线程持有锁,他们只知道锁被其中一个线程所持有,而synchronized本身就是通过对象监视器来实现锁的,所以这个wait方法在Object中也是最好不过了。

目录
相关文章
|
4月前
|
安全 Java
Synchronized和Lock的区别
Synchronized和Lock的区别
28 0
|
8月前
|
Java
synchronized和lock的区别
synchronized和lock的区别
62 0
|
6月前
|
缓存 Java 编译器
volatile,解决内存可见性引起的问题,wait和notify
volatile,解决内存可见性引起的问题,wait和notify
|
7月前
|
Java
Lock 和 Synchronized的区别?
本章主要讲解了Lock 和 Synchronized的区别和知识点
29 0
|
8月前
|
Java
synchronized和Lock的区别
synchronized和Lock的区别
52 0
|
存储 Java API
面试官:为什么 wait/notify 必须与 synchronized 一起使用??
面试官:为什么 wait/notify 必须与 synchronized 一起使用??
129 0
面试官:为什么 wait/notify 必须与 synchronized 一起使用??
为什么 wait 方法要在 synchronized 中调用?
它们是在有 synchronized 标记的方法或 synchronized 块中调用的,因为 wait 和 nodify 需要监视对其调用的 Object。 大多数Java开发人员都知道对象类的 wait(),notify() 和 notifyAll() 方法必须在 Java 中的 synchronized 方法或 synchronized 块中调用, 但是我们想过多少次, 为什么在 Java 中 wait, notify 和 notifyAll 来自 synchronized 块或方法?
160 0
为什么 wait 方法要在 synchronized 中调用?
wait和notify 为什么要在synchronized代码块中
wait和notify 为什么要在synchronized代码块中
wait和notify 为什么要在synchronized代码块中
|
安全 Java
Lock和Synchronized的区别
Lock和Synchronized的区别
Lock和Synchronized的区别
线程 - wait & sleep 区别
线程 - wait & sleep 区别
90 0