0

如果一个线程试图获取一个锁并取得锁,它应该进入休眠状态并保持睡着状态,直到释放锁。如果一个线程释放一个锁(并且它由创建它的线程取得),它应该唤醒线程。实现锁定和阻塞线程

我的问题是,如果我们唤醒锁地址上的所有线程与锁地址上的单线程(锁释放后)是否有区别?如果我们要唤醒一个单独的线程,哪一个线程有意义醒来,第一个线程应该锁定在锁定地址上?

我可以看到唤醒一个线程的一些优势,因为如果我们全部唤醒,n-1可能会回到睡眠状态。但我不知道唤醒单线程是否有缺点。

+2

如果它是一个锁(互斥,临界区),有什么能唤醒一个以上的线程在等待它的意义呢?当它似乎是唯一可能发生的事情时,为什么“他们*可能会*重新入睡”? –

回答

2

我相信你混淆窗户锁(互斥,临界区)与.net显示器(在C#中可以使用关键字锁定为语法糖进入/退出块。)

的Windows互斥和关键部分只能进入和退出,即只有一个队列与它们相关联。队列中的所有线程都会等待锁被释放,当发生这种情况时,队列上的下一个线程将控制锁并开始运行。所有这些都自动发生。当前持有锁的线程没有任何部分,它不能选择唤醒等待锁释放的其他线程中的一个或多个线程。

.Net's Monitor有两个队列:一个就绪队列和一个等待队列。

就绪队列的行为与Win32 Mutex或Critical Section队列完全相同,并使用Enter/Leave方法进行控制。

等待队列是使用Wait/Pulse/PulseAll方法控制的单独队列。这些方法只能由持有Monitor的线程调用。当一个线程调用等待它释放监视器并进入等待队列。然后不同的线程可以调用Pulse移动一个线程或Pulse All将所有线程从等待移动到就绪队列(请记住调用Pulse/PulseAll的线程持有Monitor)。

从计算机科学的角度来看监控器是需要同步线程(信号量,事件,互斥体,障碍等可以用监视器实现的)的单个原语,从实际的角度来看,监视器作为互斥体以及需要由两个线程锁定步骤。但大多数情况下,使用事件时代码更具可读性。

延伸阅读:

Wikipedia page about Monitors for the historic/computer science aspect

MSDN Monitor class

+0

由于OP在任何地方都没有提到.Net,所以我想知道为什么你从一开始就谈论.Net监视器。如果OP感到困惑的是,监视器是.Net特有的东西,但这是一个通用的概念,否则你会很好地解释它。 –

+0

@Pavel你可能是对的。在我看来,就像给出这个问题的最可能的错误。 .Net监视器是使用“锁定”关键字唯一受欢迎的同步原语,可以唤醒其他线程。我可以编辑答案以清楚地说明Monitor是一个通用的概念,并不特别与.Net联系在一起。 –