`LockSupport.park()` 可以替换 `Object.wait()` 吗?

Can `LockSupport.park()` replace `Object.wait()`?

目前我正在 Java 学习并发编程。我注意到 Java 1.6 中引入的 LockSupport.park()Object.wait() 更容易使用,Object.wait() 的典型用法是

// Thread1
synchronized (lock) {
    while (condition != true) {
        lock.wait()
    }

    // do stuff
}

// Thread2
synchronized (lock) {
    condition = true;
    lock.notify();
}

而且我想我可以使用 LockSupport.park() 重写它,比如

// Thread1
while (condition != true) {
    LockSupport.park();
}

// do stuff

// Thread2
condition = true;
LockSupport.unpark(Thread1);

通过使用LockSupport.park(),繁琐的synchroinzed块消失了。

我的问题是,我是否应该总是更喜欢 LockSupport.park() 而不是 Object.wait()Object.wait()有没有比LockSupport.park()更好的地方,比如性能?

wait/notify背后的想法是通知不是线程特定的,通知者不必知道需要通知的特定线程,它只是告诉锁(或条件,对于 ReentrantLock ) 它正在通知,锁和它们之间的 OS 调度器决定谁得到通知。

我预计在大多数情况下,通知程序不想知道哪个线程需要取消停放,因此 wait/notify 将是这些情况下更好的选择。使用 park/unpark,您的代码必须知道更多,并且失败的机会也会更多。您可能认为同步块很乏味,但真正乏味的是整理出某些东西在应该有的时候没有被取消停放的情况。

请注意,在您的第二个示例中,您的条件需要是易变的或原子的,或者其更新跨线程可见的其他内容。

不,Locksupport.park()/unpark() 不能代替Object.wait()。

Locksupport.park()/unpark() 不需要你获取锁,但是 Object.wait() 确实需要你有 synchronized 关键字来保护它。让我告诉你为什么,

while (condition != true) 
  LockSupport.park();

在没有同步或其他保护的情况下,某些其他线程可以更改这两行代码之间的条件变量。所以你的代码可能 park/unpark 其实不应该。