struct __pthread_mutex中__held自旋锁的作用及pthread_mutex含自旋锁的原因
关于pthread_mutex中自旋锁的疑问解答
1. struct __pthread_mutex结构体中__pthread_spinlock_t __held的作用
__held自旋锁的核心作用是标记互斥锁的持有状态,并实现锁所有权的高效传递:
- 当线程成功获取pthread_mutex时,会持有这个__held锁,以此标识自己是当前互斥锁的所有者;
- 在解锁流程中,线程不会主动释放__held锁,而是直接将它的所有权转移给等待队列中被唤醒的下一个线程。这种设计省去了“释放锁→下一线程重新竞争获取”的步骤,大幅减少了锁操作的开销,尤其适合高并发、锁持有时间短的场景。
2. 为何pthread_mutex中会包含自旋锁?
pthread_mutex本质是阻塞型互斥锁,但引入自旋锁是为了优化性能,减少上下文切换开销,具体原因包括:
- 短时间等待优化:当线程尝试获取互斥锁时,如果锁仅被短时间持有,线程可以通过自旋锁进行短暂的忙等(自旋),避免立即进入内核态阻塞——线程的阻塞与唤醒会带来较大的上下文切换开销,自旋等待能在锁快速释放时节省这部分成本;
- 保护内部数据结构:结构体中的
__lock自旋锁用于保护互斥锁自身的内部状态(如等待队列、所有者信息等),确保对这些数据的并发访问是线程安全的; - 实现高效的所有权传递:结合
__held的设计,自旋锁能实现锁所有权的快速转移,避免了传统锁释放后重新竞争的开销,进一步提升并发场景下的性能。
参考代码(含中文注释)
互斥锁结构体定义
/* 用户可见的互斥锁结构体 */ struct __pthread_mutex { __pthread_spinlock_t __held; __pthread_spinlock_t __lock; /* 在cthreads中,mutex_init不会初始化第三个指针,因此我们不能依赖它的值做任何操作 */ char *cthreadscompat1; struct __pthread *__queue; struct __pthread_mutexattr *attr; void *data; /* 到这里为止,我们完全兼容cthreads以及libc的预期 */ void *owner; unsigned locks; /* 如果为NULL则使用默认属性 */ };
互斥锁解锁函数片段
/* 解锁互斥锁,调度等待中的线程 */ int __pthread_mutex_unlock (pthread_mutex_t *mutex) ... /* 我们不释放MUTEX->held:而是将所有权转移给被唤醒的线程 */
内容的提问来源于stack exchange,提问作者Zegang
相关产品推荐
相关产品推荐

