多线程竞争下PTHREAD_MUTEX_ADAPTIVE_NP为何表现类似PTHREAD_MUTEX_TIMED_NP?
关于
PTHREAD_MUTEX_ADAPTIVE_NP互斥锁公平性的疑问解答 你观察到的这个现象其实挺耐人寻味的——按说PTHREAD_MUTEX_ADAPTIVE_NP作为自适应互斥锁,设计初衷是靠自旋重试降低上下文切换开销,看起来应该是“谁抢到算谁的”不公平模式,但实际测试里却呈现出类似公平锁的FIFO排队行为,这和你看到的Kaz先生的说法好像矛盾,对吧?
咱们得先拆解一下PTHREAD_MUTEX_ADAPTIVE_NP的实际实现逻辑,它其实是混合了自旋和内核排队的模式,不是纯粹的自旋锁:
- 当线程尝试获取锁失败时,不会立刻进入内核休眠,而是会先自旋重试若干次(重试次数通常和CPU核心数、系统负载相关);
- 如果自旋了好几次还是拿不到锁,线程就会通过
futex系统调用进入内核的等待队列,进入休眠状态。
你看到的“等待最久的线程先拿到锁”,恰恰是因为所有竞争的线程(B、C、D)都已经走完了自旋阶段,进入了内核的等待队列。而大多数Linux内核的线程等待队列是按FIFO顺序唤醒的——也就是先进入队列的线程(等待最久的)会最先被唤醒并获取锁。
那Kaz先生说它“不适用于对公平性有要求的场景”错了吗?当然没错,因为自适应互斥锁的“不公平”体现在自旋阶段的插队可能性:
举个例子,如果线程A释放锁的瞬间,刚好有线程E正在自旋重试,那E可以直接跳过等待队列里的线程,抢先拿到锁。这时候队列里等待更久的线程就会被“插队”,破坏了严格的FIFO顺序。这种场景下,它就无法保证公平性。
简单总结一下:
- 当所有竞争线程都进入内核等待队列时,内核会按FIFO调度,表现出你看到的“等待最久先拿锁”;
- 但只要有线程还在自旋阶段,就存在插队的可能,这才是它不适合强公平性场景的核心原因。
内容的提问来源于stack exchange,提问作者JM_Ma
相关产品推荐
相关产品推荐

