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

时间:2012-02-24 07:57:02

标签: c multithreading pthreads mutex semaphore

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

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

6 个答案:

答案 0 :(得分:6)

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

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

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

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

通常情况下,如果线程调用类似usleep之类的东西来暂停其自己的执行一段时间,则表示线程处于休眠状态。这与阻塞相反,它正在等待另一个线程提供的特定信号。

答案 1 :(得分:4)

请看一下: https://stackoverflow.com/a/24582076/3163691

是的,互斥信号量正在同步内核对象,当线程尝试 获取 时,其中一个如果该对象已被其他线程拥有,则此线程将被置于 sleep

正如您已经猜到的,这个 睡眠 是一个至关重要的功能,因为它允许其他线程做更多有用的工作,而不仅仅是“循环/轮询”。

当拥有对象 的线程 时,这些线程的 睡眠 结束。

[ OS计划程序不会将任何执行切片提供给休眠线程]。

将其与锁定& spinlock ,其中一个主题处于“循环/忙碌等待”状态。国家浪费宝贵的CPU时间几乎没有。因此,用户代码中应避免使用自旋锁。请改用关键部分互斥信号量

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

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

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

希望这有帮助。

答案 2 :(得分:0)

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

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

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

答案 3 :(得分:0)

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

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

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

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

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

答案 4 :(得分:0)

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

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

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

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

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

答案 5 :(得分:-1)

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

由于