【问题标题】:Are there any equivalents to the futex in Linux/Unix?Linux/Unix 中的 futex 有什么等价物吗?
【发布时间】:2014-04-24 19:33:48
【问题描述】:

我正在寻找可以在 C/C++ 中用于轮询的东西(如 selectkqueueepoll 即不是忙轮询) .换句话说,我需要阻塞一个线程,然后在另一个线程中以尽可能少的开销唤醒它。

mutex + condition variable 有效,但开销很大。 futex 也可以,但这仅适用于 Linux(或者可能不是?)。只要 polling 本身正常工作,就不需要额外的同步,例如当我在两个线程中调用 waitwake 时没有比赛。

编辑:如果 FreeBSD 中不存在这样的“工具”,如何使用 C++11 内置类型和系统调用创建一个?

Edit2:由于这个问题已迁移到 SO,我想让它更通用(仅适用于 FreeBSD)

【问题讨论】:

  • 您是否还需要阻止多个来源,还是只阻止一个? selectpoll 等通常用于(解)多路复用多个 fd,而不仅仅是阻塞一个。
  • @Useless One 已经足够好了。你是对的,select 不是一个很好的例子。我提到它只是为了说明我不想忙着等待
  • 迁移后,我对这个问题的“目标”感到困惑。您是否正在寻找适用于 FreeBSD、POSIX 或标准 C++11 的答案?
  • @MichaelBurr 我正在使用具有 POSIX 和 C++11 的 FreeBSD。所以我打开了所有这三个选项
  • @GuLearn 你能找到相关的吗?

标签: c++ c multithreading


【解决方案1】:

信号量不是互斥体,而且开销会稍微少一些(例如,避免互斥体+condvar 重新锁定)

请注意,由于任何线程休眠直到唤醒的解决方案都将涉及内核系统调用,因此它仍然不便宜。假设 x86_64 glibc 和 FreeBSD libc 都是合理的实现,那么不可避免的成本似乎是:

  1. 计数的用户模式同步(使用 CAS 或类似方法)
  2. 等待队列和线程睡眠/等待的内核管理

我假设您担心的 mutex + condvar 开销是 cond_wait->re-lock->unlock 序列,这里确实避免了。

【讨论】:

  • 我对系统调用和上下文切换没问题,因为我有很多不那么忙的线程。我对信号量的担心是它可能比mutex + condition variable: freebsd.org/cgi/man.cgi?query=sema&sektion=9 效率更低。不过,Ubuntu 中的 man sem_overview 并没有说明性能。我可能需要自己比较一下。
  • x86 的 glibc 源代码显示它使用 futex 系统调用来实现信号量来管理服务员,以及用于计数器的用户空间 CAS(例如this pseudocode)。我不知道它会便宜多少,但您需要自己调查其他平台上的行为。
  • FreeBSD libc code 看起来很相似...
  • sem_t 在争用较低时似乎比 std::mutex + std::condition_variable 快。
【解决方案2】:

您需要信号量而不是互斥锁用于 to 线程之间的信号传输..

http://man7.org/linux/man-pages/man3/sem_wait.3.html

信号量可以像计数器一样使用,例如,如果您有一个队列,则每次插入消息时都会递增(发布)信号量,而接收者会在接收到的每条消息时递减(等待)信号量。如果计数器达到零,接收器将阻塞,直到发布某些内容。

所以一个典型的模式是把一个互斥量和一个信号量组合起来;

sender:
    mutex.lock
    insert message in shared queue
    mutex.unlock
    semaphore.post

receiver:
    semaphore.wait
    mutex.lock
    dequeue message from shared structure
    mutex.unlock

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-11
    • 2012-10-17
    • 2023-03-28
    • 2018-07-10
    • 1970-01-01
    • 2010-12-28
    相关资源
    最近更新 更多