在锁定状态下发信号通知线程

时间:2013-07-23 14:49:32

标签: java concurrency locking reentrantlock

我从这个API中采取了以下几点,我想知道以下两点之间的区别:

  
      
  1. 等待线程以FIFO顺序发出信号。

  2.   
  3. 从中返回的线程的锁重新获取的顺序   等待方法与最初获取的线程相同   锁定,在默认情况下未指定,但用于公平锁定   赞成那些等待时间最长的线程。

  4.   

它与Condition类有关,它通常由ReentrantLock方法.newCondition()返回,我引用它的位解释了Condition方法与常规监视方法之间的区别对象类。

“等待线程以FIFO顺序发出信号”。我认为只要创建lock公平或不公平,等待线程以FIFO顺序发出信号的事实完全无关紧要不是吗?因为无论如何,它们是否已被构造,是否公平,这决定了它们如何排队。

只是要求确认。

提前致谢。

3 个答案:

答案 0 :(得分:1)

请参阅以下问题的答案:

  

1.等待线程以FIFO顺序发出信号。

当我们调用Condition的await()方法时,线程进入等待状态,上面的语句指的是这些处于等待状态的线程如何发出信号。因此,如果线程T1在T2之前进入等待状态,则T1将在T2之前发出信号。

  

2.从等待方法返回的线程的锁重新获取的顺序与最初获取锁的线程的顺序相同,默认情况下未指定,但是公平锁有利于那些等待时间最长的线程。

继续上述语句,当等待线程发出信号时,它倾向于重新获取锁定。虽然上面的声明说T1将在T2之前发出信号,但是当涉及到重新获取锁时,重新获取的顺序使用Lock定义的概念。因此,它取决于Lock对象的创建方式。在创建Lock时,您可能已指定了一个公平参数:

ReentrantLock(boolean fair)

如果是,则使用该参数,否则将发生锁的默认行为,您可以在此link

上阅读有关ReentrantLock Locks的更多信息。

这些陈述可能有更多的解释,只是试图在这里最好地详述我的理解。希望能够澄清。

干杯!!

答案 1 :(得分:0)

  

只要创建一个公平或不公平的锁,等待线程以FIFO顺序发出信号这一事实完全无关紧要,不是吗?因为无论如何,它们是否已被构造,是否公平,这决定了它们如何排队。

我认为这是相关的。

考虑T1和T2在条件C上等待的情况(T1等待超过T2),T3在监视器内运行,T4正在等待其初始锁定获取。 T3发出信号C并离开显示器释放锁定。假设没有发生虚假唤醒

如果锁定公平,T4肯定会在T1之前获得锁定,但等待线程以FIFO顺序发出信号的事实将保证T1将在T2之前获得锁定。

此外,如果锁定不公平,我们不能说哪个线程将首先在T1和T4之间获取锁定,但是再次以FIFO顺序发出等待线程信号的事实保证了T1将在T2之前获得锁定,前提是在T1获得锁定之前不会发生其他信号(例如,如果T1负责下一个信令)。

答案 2 :(得分:0)

我认为源代码可以为我们提供更多有关其工作原理的线索。 ReentrantLock.newCondition() AbstractQueuedSynchronizer 中返回 ConditionObject 。以下是源代码链接AQS source code

  

1.等待线程以FIFO顺序发出信号。

AbstractQueuedSynchronizer 中有两个队列。

一个用于等待锁定(只需将其称为锁定等待队列),您将看到两个易变变量 head tail AbstractQueuedSynchronizer 的类定义,而fairness参数将影响此队列的行为。当您新建一个公平的 ReentrantLock 并呼叫获取时,AQS将调用 FairSync tryAcquire 检查当前线程是否是第一个在锁定等待队列中等待的线程,请参阅 hasQueuedPredecessors

另一个队列是 ConditionObject 定义中的信号队列,你会看到两个变量 firstWaiter lastWaiter 。当等待时被调用,一个节点将添加到队列的尾部,当调用 signal 时,来自头部的节点将出列并添加到锁定等待队列以重新获取锁定。添加到锁等待队列并不意味着它会被唤醒,但信号后会调用 Lock.unlock(),这会唤醒服务员,见 unparkSuccessor

  

2.从等待方法返回的线程的锁重新获取的顺序与最初获取锁的线程的顺序相同,默认情况下未指定,但是公平锁有利于那些等待时间最长的线程。

等待方法唤醒并不意味着保持锁定,它会调用 acquireQueued 来重新获取锁定并可以再次停放。 根据我的理解,最初获取锁定的顺序与调用等待的顺序相同,因此与调用 acquireQueued 的顺序相同,让我困惑的是< strong>但是对于公平锁定有利于那些等待时间最长的线程。,当从 await 中醒来时,在我看来,它将是锁定等待队列中的第一个线程,当致电 acquireQueued 并检查 p == head&amp;&amp; tryAcquire(arg),锁定是否公平无效。

希望这有帮助,如果我错了就让我。