为什么 POSIX 互斥锁被认为比 futexes 更重或更慢?pthread 互斥锁类型的开销来自哪里?我听说 pthread 互斥体是基于 futexes 的,当没有争议时,不要对内核进行任何调用。看起来 pthread 互斥锁只是围绕 futex 的“包装器”。
是否只是函数包装调用中的开销以及互斥函数“设置” futex 的需要(即,基本上是为 pthread 互斥函数调用设置堆栈)?或者 pthread 互斥体是否发生了一些额外的内存屏障步骤?
创建 Futex 是为了提高 pthread 互斥体的性能。NPTL 使用 futexes,LinuxThreads 早于 futexes,我认为这是“较慢”考虑的地方。NPTL 互斥锁可能有一些额外的开销,但应该不会太多。
编辑: 实际开销基本上包括:
因此,几个周期(典型情况)到几个周期 + 一个分支错误预测 + 一个额外的缓存未命中(非常糟糕的情况)。
对您的问题的简短回答是,众所周知,futex 的实现效率尽可能高,而 pthread 互斥锁可能会也可能不会。至少,pthread 互斥体具有与确定互斥体类型相关的开销,而 futex 则没有。因此,futex 几乎总是至少与 pthread 互斥锁一样有效,除非有人想出一些比 futex 更轻的结构,然后发布一个 pthreads 实现,将其用作其默认互斥锁。
从技术上讲,pthread 互斥锁并不比 futex 慢或快。pthread 只是一个标准的 API,所以它们是慢还是快取决于该 API 的实现。
特别是在 Linux 中,pthread 互斥锁被实现为 futex,因此速度很快。实际上,您不想使用 futex API 本身,因为它很难使用,在 glibc 中没有适当的包装函数,并且需要在汇编中进行编码,这将是不可移植的。对我们来说幸运的是,glibc 维护人员已经在 pthread 互斥 API 的底层为我们编写了所有这些代码。
现在,因为大多数操作系统都没有实现 futexes ,所以程序员通常所说的 pthread mutex 是指从 pthread mutex 的通常实现中获得的性能,也就是说,速度较慢。
因此,在大多数符合 POSIX 的操作系统中,pthread 互斥锁是在内核空间中实现的,并且比 futex 慢,这是一个统计事实。在 Linux 中,它们具有相同的性能。可能还有其他操作系统在用户空间中实现了 pthread 互斥锁(在无竞争的情况下),因此性能更好,但我目前只知道 Linux。
因为它们尽可能地留在用户空间,这意味着它们需要更少的系统调用,这本质上更快,因为用户模式和内核模式之间的上下文切换很昂贵。
当您谈论 POSIX 线程时,我假设您正在谈论内核线程。完全有可能拥有一个完全用户空间的 POSIX 线程实现,它不需要系统调用,但有自己的其他问题。
我的理解是 futex 介于内核 POSIX 线程和用户空间 POSIX 线程之间。
在 AMD64 上,futex 是 4 个字节,而 NPTL pthread_mutex_t 是 56 个字节!是的,有很大的开销。