关于并发的问题

Questions about concurrency

如果我理解正确的话,synchronized 应该足以确保一次只有一个线程可以访问资源:

当一个线程想要执行一个同步块时,它获取监视器并在同步块结束时自动释放它,与此同时,所有其他试图访问已被监视器占用的同步块的线程是放入队列,只要程序是 运行.

,就会继续尝试访问同步方法

如果我在同步块内调用 wait(),那么我最终可能会在同步块内有多个线程,而且我还被迫在块末尾调用 notify() 以避免线程永远等待。

First of all, is what I just stated correct? If it is not, what's wrong?

前两段是正确的。关于等待/通知的第三段大部分是正确的。不过有几点:

  • 一些线程需要调用notifynotifyAll。但不一定非得是这一个。
  • 您可以随时调用,而不仅仅是在块的末尾。无论哪种方式,通知都不会发生,直到当前线程离开块。
  • 等待从未到达的通知的线程不一定永远卡住。例如,线程中断将导致 waitInterruptedException.
  • 终止

If it is, what are the most commons situations where synchronized should be used with wait() and notify()?

“应该”这个词是一个有内涵的词。您 可以 使用 wait()notify() 的情况是一个线程需要等待某个事件发生的情况。 (通常这用于实现条件变量。)但根据具体情况,可能有更好的方法。

此外,如果没有 持有关联的互斥体,则不能使用wait()notify() 。 (如果你尝试这样做,你会得到一个例外!)


In general, if I'm making the code more complex by adding wait() and notify() to synchronized, would it be better to just use a more sophisticated tool like ReentrantLocks?

一般不会。

如果有更高级别的并发 classes 可以做你想做的事情,通常最好使用它们而不是原始互斥锁 + 等待/通知。但情况并非总是如此。

您提到了 ReentrantLock。这个 class 实际上只是“在类固醇上”的类似互斥锁的锁。它们有一些原始互斥锁不可用的特性(比如 tryLock 和查看哪些线程正在等待),但是如果你不需要 需要 额外的特性就没有了使用 ReentrantLock 优于原始互斥体的真正优势。 (一个可能的 缺点Lock classes 不会在块退出时自动释放。所以你真的需要将它们与 try ... finallytry 与资源。)