【问题标题】:Can `LockSupport.park()` replace `Object.wait()`?`LockSupport.park()` 可以替换 `Object.wait()` 吗?
【发布时间】:2017-01-17 20:15:51
【问题描述】:

目前我正在学习 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() 做得更好?

【问题讨论】:

标签: java multithreading locking wait


【解决方案1】:

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

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

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

如果没有同步或其他保护,其他一些线程可以更改这两行代码之间的条件变量。因此,您的代码可能会在不应该停放/取消停放时停放/取消停放。

【讨论】:

    【解决方案2】:

    等待/通知背后的想法是通知不是特定于线程的,通知程序不必知道需要通知的特定线程,它只是告诉锁(或条件,对于 ReentrantLock)它正在通知,它们之间的锁和操作系统调度程序决定谁收到通知。

    我希望大多数时候通知程序不想知道哪个线程需要取消驻留,因此等待/通知对于这些情况将是更好的选择。通过停放/取消停放,您的代码必须了解更多信息,并且会有更多失败的机会。您可能认为同步块很乏味,但真正乏味的是整理出一些在应该有的时候没有被释放的情况。

    请注意,在您的第二个示例中,您的条件需要是 volatile 或 Atomic 或其他在线程间可见其更新的东西。

    【讨论】:

    • 在探索了相关类的javadoc之后,我意识到wait()的替换是Conditionsynchroinzed的替换是LockCondition 需要派生自Lock 也反映了wait()synchronized 的关系。 LockSupport.park() 是它们的基础。
    猜你喜欢
    • 1970-01-01
    • 2013-09-05
    • 1970-01-01
    • 1970-01-01
    • 2017-10-01
    • 2011-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多