浅析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中也是最好不过了。

目录
相关文章
|
7月前
|
安全 Java
Synchronized和Lock的区别
Synchronized和Lock的区别
76 0
|
2月前
|
Java
理解wait()、notify()和notifyAll()
【10月更文挑战第9天】
|
6月前
|
Java
wait()和notify():JAVA多线程世界的“信号兵”
【6月更文挑战第20天】在Java多线程中,`wait()`和`notify()`作为Object类的方法,扮演着线程间协调者的角色。`wait()`让线程等待并释放锁,`notify()`或`notifyAll()`唤醒等待的线程。在生产者-消费者模型中,它们用于同步访问资源,例如队列。当队列满或空时,线程调用wait()暂停,另一方完成操作后用notify()唤醒。理解并正确使用这些“信号兵”对构建高效的多线程程序至关重要。
41 0
|
6月前
|
安全 Java
synchronized与Lock
synchronized与Lock
|
7月前
|
调度
多线程之wait&notify
多线程之wait&notify
|
缓存 Java 编译器
volatile,解决内存可见性引起的问题,wait和notify
volatile,解决内存可见性引起的问题,wait和notify
为什么 wait 方法要在 synchronized 中调用?
它们是在有 synchronized 标记的方法或 synchronized 块中调用的,因为 wait 和 nodify 需要监视对其调用的 Object。 大多数Java开发人员都知道对象类的 wait(),notify() 和 notifyAll() 方法必须在 Java 中的 synchronized 方法或 synchronized 块中调用, 但是我们想过多少次, 为什么在 Java 中 wait, notify 和 notifyAll 来自 synchronized 块或方法?
198 0
为什么 wait 方法要在 synchronized 中调用?
|
存储 Java API
面试官:为什么 wait/notify 必须与 synchronized 一起使用??
面试官:为什么 wait/notify 必须与 synchronized 一起使用??
168 0
面试官:为什么 wait/notify 必须与 synchronized 一起使用??
多线程之——wait/notify
多线程之——wait/notify
70 0
|
安全 Java
Java并发编程之Wait和Notify
Java并发编程之Wait和Notify
135 0
Java并发编程之Wait和Notify