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

问题描述 投票:0回答:2

目前我正在学习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
2个回答
5
投票

wait 和 park 这两个东西,看起来很像,其实差别很大

调用

wait
发生在用
synchronized
锁定的上下文中。您有线程正在测试的某些条件,您正在测试正在同步的对象的状态,以确定线程是否可以继续。等待/通知进程使用锁作为发送通知的中间人,操作系统调度程序负责通知谁。所以这里的用例是你有一些组件的状态你想保护它免受并发访问,如果一个线程不能取得进展,你希望它等到它可以。

其中的一个核心部分是您不是在等待线程中扮演木偶大师,您的代码不关心接下来通知谁,而是将其委托给调度程序。

对于公园来说,事情是不同的,没有像等待那样的锁定,它更像是一个动手的木偶大师。您的代码告诉各个线程休眠或唤醒。

LockSupport的API文档中有一个警告:

这些方法旨在用作创建更高级别同步实用程序的工具,它们本身对大多数并发控制应用程序没有用处。 park 方法仅设计用于以下形式的构造:

 while (!canProceed()) { ... LockSupport.park(this); }

canProceed 或任何其他在调用 park 之前的操作都需要锁定或阻塞。因为每个线程只关联一个许可证,所以 park 的任何中间使用都可能干扰其预期效果。

您的具体示例取决于对条件测试的锁定,这是文档告诉您不要使用 park 的内容。等待之后,您还需要锁定“做事”部分。

如果你需要比

synchronized
更强大的东西,那么你可能会看看 ReentrantLock 或不同的非阻塞方法,但是 park/unpark 更像是一个低级的助手,而不是准备在你的应用程序中使用的东西。

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


1
投票

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

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

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

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

© www.soinside.com 2019 - 2024. All rights reserved.