与我的一个朋友,我们不同意在用户空间级别(在pthread库)处理同步。
一个。 我认为,在一个pthread_mutex_lock,线程积极等待。 这意味着Linux调度程序启动这个线程,让它执行他的代码,应该看起来像这样:
while (mutex_resource->locked);
然后,另一个线程被调度,可能释放locked
字段等等。所以这意味着调度程序等待线程完成其调度时间,然后切换到下一个线程,而不pipe线程在做什么。
湾 我的朋友认为,等待的线程告诉内核“嘿,我睡着了,不要等我”。 在这种情况下,内核会立即安排下一个线程,而不需要等待当前线程完成其调度时间 ,知道该线程正在hibernate。
从我在pthread的代码中看到的,似乎有处理锁的循环。 但也许我错过了一些东西。
在embedded式系统中,防止内核等待是有意义的。 所以他可能是对的(但我希望他不会:D)。
谢谢!
一个。 我认为,在一个
pthread_mutex_lock
,线程积极等待。
是的,glibc的NPTL pthread_mutex_lock
有主动等待(旋转),但是旋转仅用于非常短的时间,并且仅用于某些类型的互斥体。 在这个数量之后,通过用WAIT参数调用linux 系统调用futex
, pthread_mutex_lock
将进入休眠状态。
只有类型为PTHREAD_MUTEX_TIMED_NP
互斥体才会旋转,默认为PTHREAD_MUTEX_TIMED_NP
(普通互斥体),不旋转。 在MAX_ADAPTIVE_COUNT
源中检查MAX_ADAPTIVE_COUNT
)。
如果要执行无限旋转(主动等待),请使用带有pthread_spinlock_t
-types锁定的pthread_spin_lock
函数。
我会考虑你的问题的其余部分,就像你使用pthread_spin_lock
:
然后,另一个线程被调度,可能释放锁定的字段等等。所以这意味着调度程序等待线程完成其调度时间,然后切换到下一个线程,而不管线程在做什么。
是的,如果CPU内核出现争用,那么即使另一个线程是解锁线程所需的互斥锁(spinlock)的线程,主动旋转的线程也可能阻止其他线程执行。
但是,如果没有争用(没有线程超额订阅),并且线程被安排在不同的核心上(巧合,或者通过手动设置与sched_setaffinity
或pthread_setaffinity_np
的cpu亲和力), sched_setaffinity
将使您能够更快地进行,然后使用基于OS的futex 。
湾 我的朋友认为,等待的线程告诉内核“嘿,我睡着了,不要等我”。 在这种情况下,内核会立即安排下一个线程,而不必等待当前线程完成。
是的,他是对的。
futex
是现代的说OS的方式,这个线程正在等待内存中的某些值(用于打开一些mutex
); 在目前的实施中, futex
也让我们的线程睡觉。 如果内核知道何时唤醒该线程,则不需要唤醒它进行旋转。 它是如何知道的? 锁所有者在执行pthread_mutex_unlock
时会检查是否还有其他线程在这个互斥锁上休眠。 如果有的话,锁的所有者将调用futex
与FUTEX_WAKE
,告诉OS唤醒某个线程,注册为这个互斥锁的卧铺。
如果线程将自己注册为OS中的服务器,则不需要旋转。
一些用gdb调试这个测试程序:
#include <pthread.h> #include <stdlib.h> #include <string.h> #include <time.h> pthread_mutex_t x = PTHREAD_MUTEX_INITIALIZER; void* thr_func(void *arg) { pthread_mutex_lock(&x); } int main(int argc, char **argv) { pthread_t thr; pthread_mutex_lock(&x); pthread_create(&thr, NULL, thr_func, NULL); pthread_join(thr,NULL); return 0; }
显示在互斥体上调用pthread_mutex_lock
导致调用一个系统调用futex
,并将op
参数设置为FUTEX_WAIT
( http://man7.org/linux/man-pages/man2/futex.2.html )
这是FUTEX_WAIT的描述:
FUTEX_WAIT
此操作自动验证futex地址uaddr仍包含值val,并在此futex地址上休眠等待FUTEX_WAKE。 如果timeout参数为非NULL,则其内容描述等待的最大持续时间,否则为无限。 参数uaddr2和val3被忽略。
所以从这个描述我可以说,如果一个互斥锁被锁定,那么一个线程将会睡眠,而不是主动等待。 它将睡眠,直到futex与op等于FUTEX_WAKE
被调用。