同步块背后

Behind Synchronized Block

Java 中的同步块在多线程中工作时是一个很棒的功能,这种情况很常见。我知道它们的大部分工作原理,但我想更确定它们在与 wait 和 notify(All) 结合使用时的工作原理。

通常当一个线程进入一个同步块时,在第一个线程离开之前没有其他线程可以进入这个块。然而,在同步对象上调用 wait 时情况并非如此。如果是这样,另一个线程将无法调用 notify(All),这需要在调用之前与对象同步。

那么调用wait是不是让调用脱离了同步?或者 java 如果在不同的块中发现 notify(All) 只是抛出异常?此外,当从一个同步块调用 wait 然后从另一个同步块调用 notify(All) 时,一个线程是否等待另一个完成后再继续,如果是,是哪个线程?

现在我可以设置一个快速测试来回答我所知道的大部分问题。但它不会回答更技术性的问题,我相信这里有人可以。我不仅对什么和什么时候感兴趣,而且对为什么感兴趣。尝试搜索一些文档信息,但找不到有关 wait/notify(All) 的任何有用信息。

编辑:

如果其他人应该感兴趣,这是测试结果。如果我们有线程 1、线程 2 和线程 3,其中前两个等待释放,第三个等待释放它们,顺序将是这样的。

  1. 线程1进入并调用wait()
  2. 线程2进入并调用wait()
  3. Thread3进入并调用notifyAll()
  4. 线程 3 始终完成
  5. 但是等待线程没有特定的顺序。哪个先执行是完全随机的,与他们调用 wait() 的顺序无关。然而,调用 notify(All) 的线程将始终在任何等待线程继续之前完成。

是的,它有点特别。 wait 释放在 synchronized block 中获取的 lock 并暂停它的 thread (获取锁的线程)这意味着其他线程将被允许获取锁并修改状态。 现在 notify 或 notifyAll 将唤醒睡着的 thread/s 并重新获取 lock