【问题标题】:When does the thread that calls Lock.lock() returns from the call, when the the lock is not available immediately?调用 Lock.lock() 的线程何时从调用中返回,当锁不能立即可用时?
【发布时间】:2018-02-11 19:04:27
【问题描述】:

来自文档:

Condition.signalAll() 的文档说,

'唤醒所有等待的线程。 如果有任何线程正在等待这种情况,那么它们都会被唤醒。每个线程必须重新获取锁才能从等待返回。 '

上面提到的等待的线程包括调用了一些重载变体的线程

Condition.await(...),

其文档说“与此条件关联的锁被自动释放,当前线程出于线程调度目的而被禁用并处于休眠状态直到...”

讨论案例: 因此,假设一个线程出于线程调度目的而被禁用,并在调用Condition.await(...) 后处于休眠状态,稍后在另一个线程调用Condition.signalAll() 时唤醒,并且在返回等待之前与其他线程竞争重新获取锁。

所以,我认为,线程必须从禁用状态中唤醒(线程调度目的)并在获取锁之前竞争。

标题中的问题:

Lock.lock() 的文档说,

'如果锁不可用,则当前线程将被禁用以进行线程调度,并处于休眠状态,直到获得锁为止。'

现在,由于在调用lock() 方法时锁不可用,因此出于线程调度目的而被禁用并处于休眠状态的线程怎么办?

这样的线程何时会从禁用状态中唤醒并竞争,以便获得锁?

注意:

1.所有提到的Condition 对象都是指从讨论中的同一个Lock 对象获得的单个Condition 对象。

2.这种情况不会出现在隐式锁中,因为所有调用同步代码的线程只是相互阻塞并竞争锁而不会禁用自己。

【问题讨论】:

  • 我不明白你的困惑。它说在获得锁之前处于休眠状态
  • 表示直到当前线程获得锁为止。请参阅lockInterruptibly() 的文档,因为lock()lockInterruptibly() 相同,只是lock() 方法不会引发异常。我只是不考虑当前线程获取锁的情况,因为它永远不会唤醒
  • 获取锁使其唤醒。
  • 或者您是在问收购是如何进行的?
  • 你被英语卡住了。当线程唤醒时,它被认为是获取了锁。获取技术是一个实现细节。

标签: java multithreading concurrency synchronization


【解决方案1】:

因此,我认为,线程必须从其禁用状态中唤醒(出于线程调度目的)并在获取锁之前竞争。

正确。一些系统在重新启用它以作为“释放锁”过程的一部分进行调度之前将锁预先分配给线程。但更典型的设计就是简单地重新调度线程,让它竞争锁。

现在,由于锁在调用 lock() 方法的那一刻不可用,因此出于线程调度目的而被禁用并处于休眠状态的线程怎么办?

这样的线程何时会从禁用状态中唤醒并竞争,以便获得锁?

通常,一旦持有锁的线程释放它。典型的实现是线程在禁用自己之前将自己添加到等待锁定的线程列表中。释放锁时,释放锁的线程会检查该列表,并重新启用列表中的至少一个线程。

【讨论】:

  • 那么,您是说等待锁的线程列表中包含活动的线程(即被Condition.signalAll() 唤醒的线程)以及被Lock.lock() 禁用的线程。但是这样的列表不应该包含通过另一个条件的await(...) 方法禁用的线程,因为除非得到通知,否则这些线程不会获取锁,不是吗?
  • 这是一种可能的实现方式,是的。等待竞争被禁用的锁的线程在一个列表中。当线程释放锁时检查该列表。
  • 我终于明白每个实现都是有意义的,我问的问题是实现细节的一部分。
【解决方案2】:

线程出于调度目的而被禁用,这意味着它不会获得 CPU 时间,但它仍在等待获取锁。所以不是处于RUNNABLE 状态,而是处于WAITING 状态。

当锁被释放时,线程有机会获得它或停留在WAITING,并且该过程重复。 Condition 似乎与这个问题没有任何关系。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-07
    • 2010-11-17
    • 1970-01-01
    • 2011-01-12
    相关资源
    最近更新 更多