互斥和信号量实际上做了什么?

我想要一些关于互斥和信号量的澄清。
我的问题是,

  1. 当线程试图进入由互斥锁锁定的区域时,互斥锁实际上做了什么。 它等待锁被释放? 或b。 它进入睡眠状态,直到释放锁定。 在那种情况下,如何在释放锁定时再次唤醒?
  2. 与1相同的问题,但在这种情况下它是信号量。
  3. 你能给我一些关于C中pthread中忙碌等待的代码,还有线程进入hibernate而不是等待的情况? 睡觉意味着它是阻塞还是睡觉是另一种忙碌的等待?
  4. 我想知道一些涵盖这种情况的程序,例如一些c源代码,其中实现繁忙等待,阻塞等。

当一个线程试图获取互斥锁上的锁时,如果该互斥锁已经被保持,那么通常它将使用对OS内核的调用来指示它正在等待,然后当当前持有锁的线程解锁互斥锁然后它将调用OS内核来唤醒其中一个等待的线程。

这同样适用于信号量,除非它仅在计数递减到零以下时才会阻塞,并且只有当计数增加回到零以上时才会唤醒线程。

忙碌的等待是在等待某些事情时不会阻塞或睡眠的地方,但是在循环中反复轮询,因此处理器总是很忙,但没有做任何有用的事情。

要真正实现忙碌等待,您需要一个primefaces变量,但POSIX线程不提供这样的东西,因此您无法在pthreads中真正编写忙等待。 最接近的是锁定互斥锁,读取标志,解锁互斥锁,如果未设置标志则循环。 这会反复锁定和解锁互斥锁,但不会等待数据准备就绪。 在这种情况下,您应该使用条件变量。

通常情况下,如果一个线程调用了像usleep这样的东西来暂停它自己的执行一段时间,那么你就说它正在hibernate。 这与阻塞相反,它在等待由另一个线程提供的特定信号。

请查看: https : //stackoverflow.com/a/24582076/3163691

是的, 互斥信号量都在同步内核对象,当线程试图获取其中一个时,如果该对象已被其他线程拥有,则该线程将进入hibernate状态

正如您已经猜到的那样,这种hibernate是一个至关重要的特性,因为它允许其他线程执行比“循环/轮询”更有用的工作。

当拥有该对象的线程释放它时,这些线程的hibernate结束。

[ OS Scheduler不会为hibernate线程提供任何执行切片 ]。

将它与自旋锁对比,其中线程处于“循环/忙等待”状态,浪费宝贵的CPU时间几乎什么也没做。 因此,应在用户代码中避免使用自旋锁 。 请改用临界区互斥锁信号量

从上面的链接可以看出,两个对象都是不同的,应该在最合适的上下文中使用。

互斥锁视为 ,只允许一个线程拥有它。 并且它具有许多安全属性(所有权,终止通知,递归等)。

并且,将信号量视为一个 ,它只允许指定数量的线程拥有它。 但是,它没有互斥锁的许多有用属性。

希望这可以帮助。

它取决于互斥体的类型(它的支持实现),有些人忙着回退,其他人只会睡眠内核线程对象,然后当互斥锁更新后会被唤醒,有些是两者的混合( Valve的Source引擎使用混合引擎。 它的特性还取决于它需要跨越内核/用户空间障碍的时间和频率,因为有时这可能比仅旋转更长时间更昂贵(如果你想要更多地进入旋转与睡眠方面,请参见此内容)。

互斥体通常一次用于单线程输入(尽管它们可能支持同一线程的递归输入)。 另一方面,信号量一次只允许n个线程尝试获取它(请参阅此MSDN文档或此比较英特尔文章)。

睡眠线程通常意味着它放弃其分配计算时间片直到准备好被唤醒,并且OS调度器给它另一个时间片。 您可能会发现的最佳示例实际上是在Linux内核源代码(或任何其他开源操作系统)。

  1. 当线程试图进入由互斥锁锁定的区域时,互斥锁实际上做了什么。 它等待锁被释放? 或b。 它进入睡眠状态,直到释放锁定。 在那种情况下,如何在释放锁定时再次唤醒?

当线程尝试获取互斥锁时,它会被卡住并仅在锁定被授予该线程时返回。 锁被操作系统识别,因此操作系统知道直到这样的锁可用于给线程 – 它没有别的办法。 线程停在OS内部。 只有操作系统知道现在线程拥有所有权才会重新入睡。 在单CPU系统中,如果某个其他进程处于打开状态,则只有当线程同时具有两者时,互斥锁才会返回 – CPU可用以及授予锁定!

注意:当你做fwriteselect相同的事情发生时。 由于OS知道相应的IO将花费时间,因此线程变为空闲。 当数据到达时,线程变为可运行。

  1. 与1相同的问题,但在这种情况下它是信号量。 你能给我一些关于C中pthread中忙碌等待的代码,还有线程进入hibernate而不是等待的情况? 睡觉意味着它是阻塞还是睡觉是另一种忙碌的等待?

在这两种情况下,都没有忙等待。 如果有人忙着等到你被锁定的时候才会消磨 – 你实际上没有锁定的目的! 考虑一下,假设我们有严格的单CPU案例(和一个愚蠢的操作系统)。 所以会发生什么,线程1尝试获取锁,因为锁位于线程B,因此线程A开始忙等待。 因此,CPU永远不会从线程A释放,线程B永远不会有机会在CPU上执行 – 最后两个线程都处于无用状态。 锁对线程对象没有任何作用。 但锁定过程总是停在线程上

等待,睡觉,阻止,都意味着同样的事情:

  1. 线程进行系统调用(获取互斥锁或信号量,等待一段时间,等等)

  2. 操作系统控制,运行调度程序,将线程标记为等待资源,同时更新其他线程的状态,然后控制准备运行的线程。 如果准备运行多个线程,则根据调度策略选择一个线程。

  3. 一旦资源可用(通过另一个线程进行的另一个系统调用),调度程序就会更新前一个线程的状态,从等待资源准备好运行,并且一旦调度程序策略决定,就会给予线程控制权。所以。

只要线程正在等待资源,它就不会占用CPU。 没有民意调查。

简单来说,当你关注1个锁时,Mutex是用来做东西的….信号量用于多个锁…我会尝试给你发送样本。 我记得我在C语言中有一些与信号量和互斥量相关的任务。就概念而言,这里有趣的是http://geekswithblogs.net/shahed/archive/2006/06/09/81268.aspx 🙂

谢谢