在使用信号量或互斥锁时,调用mutex_lock
或sem_wait
的程序会被挂起,进入等待状态,直到另一个线程调用unlock
或sem_post
来唤醒它。这种等待不是死循环,也不会一直消耗 CPU。
具体来说,当一个线程调用mutex_lock
或sem_wait
时,如果锁或信号量当前不可用(已被其他线程持有),该线程将被放入等待队列,并处于阻塞状态,不再消耗 CPU 资源。当其他线程释放了锁或增加了信号量的计数值时,系统会从等待队列中选择一个等待的线程唤醒它,使其继续执行。
这种唤醒机制通常是由操作系统或线程库来实现的,具体实现方式可能涉及线程调度算法和底层的系统调用。这种方式保证了线程在获取锁或信号量时的阻塞操作是高效的,不会导致 CPU 资源的浪费。
当一个线程调用mutex_lock
或sem_wait
时,如果锁或信号量当前不可用,该线程会被阻塞,并加入到等待该锁或信号量的等待队列中。这个等待队列是由操作系统或线程库维护的。
具体的工作流程如下:
线程调用
mutex_lock
或sem_wait
:当一个线程想要获得一个互斥锁或信号量时,它会调用相应的函数(如mutex_lock
或sem_wait
)。检查锁或信号量状态:系统会检查锁或信号量的状态。如果锁已经被其他线程持有,或者信号量的计数值不足以满足当前线程的需求,那么当前线程将被放入等待队列。
加入等待队列:线程被放入等待队列后,它将被挂起,不再消耗 CPU 资源。等待队列中的线程按照某种策略进行排列,通常是先进先出(FIFO)或优先级队列。
等待其他线程释放锁或增加信号量的计数值:在等待队列中的线程会等待其他线程释放锁或增加信号量的计数值。一旦锁被释放或信号量的计数值被增加,等待队列中的某个线程就会被唤醒。
唤醒等待的线程:唤醒线程的工作通常由操作系统或线程库完成。一旦有其他线程释放了锁或增加了信号量的计数值,操作系统会从等待队列中选择一个等待的线程唤醒它,并将其状态从阻塞状态改变为就绪状态,使其可以继续执行。
总的来说,等待队列的管理和线程的唤醒是由操作系统或线程库来完成的,这样可以确保线程的阻塞和唤醒操作是高效而正确的。
参考:互斥锁的实现原理