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

P b*_*sak 9 c multithreading mutex semaphore pthreads

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

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

Ant*_*ams 6

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

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

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

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

通常情况下,如果某个线程已调用类似于usleep在指定时间段内暂停其自身执行的内容,则表示该线程处于休眠状态.这与阻塞相反,它在等待由另一个线程提供的特定信号.

  • 它是如何处理的是操作系统的实现细节,但是等待线程通常不会消耗任何CPU.它被添加到操作系统的等待线程列表中,并且只有在被解锁的互斥锁发出信号时才会被唤醒. (2认同)

fan*_*nte 6

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

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

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

睡觉一个这些线程结束的时,谁拥有对象的线程释放它。

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

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

正如您从上面的链接中看到的,这两个对象是不同的,应该在最适合的正确上下文中使用。

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

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

希望这可以帮助。