是否有与Windows手动重置事件等效的UNIX/pthreads?

Bee*_*ope 7 linux concurrency multithreading mutex pthreads

简而言之,手动重置事件是同步构造,其处于"发信号"或"非信号"状态.在信号状态中,任何调用事件上的等待函数的线程都不会阻塞,执行将继续不受影响.在非信号对象上调用等待函数的任何和所有线程都将阻塞,直到事件进入信号状态.

信号和非信号状态之间的转换仅在显式调用SetEventResetEvent等函数时发生.

我在Windows上构建了一个同步机制,它使用这些手动重置事件和它们的自动重置兄弟.自动复位机制可以很容易地用信号量复制,但我很难找到手动复位变体的等价物.

特别是,虽然具有"全部通知"功能的条件变量乍一看可能看起来相似,但是当您考虑它需要关联的互斥锁时,它具有相当不同(可能是非功能性)的行为.首先,在线程可以在condvar上等待之前,它必须获取相关的互斥锁.除了获取和释放互斥锁的成本之外,这不必要地序列化所有即将等待的线程.在唤醒时,即使通知所有线程,一次只有一个线程实际上会获得互斥锁,从而产生额外的性能和并发性惩罚,因为在这种情况下互斥锁没有用处.

多CPU系统的发布情况特别差,因为所有服务员同时发布可以保证condvar和Windows事件之间的差异是可观察的 - 使用一个事件,N个线程将在N CPU系统上运行,并且可以并行运行,而使用condvar - 即使是避免雷鸣般的群体的实现 - 线程也只能通过相关的互斥锁一次泄漏.

任何指向更好地模仿手动重置事件行为的构造的指针都将非常感激.我能找到的最接近的是一个屏障 - 这允许不同步的方法和多个线程释放到屏障 - 但屏障"基于等待线程计数"而不是显式应用程序调用"中断",这是我需要的.

caf*_*caf 3

它仅适用于 Linux(我只是提到它,因为你有一个“linux”标签),但我认为你可以在系统调用上构建类似的东西futex。请参阅Ulrich Drepper 关于 Futexes 的论文了解血淋淋的细节。

非常粗略地,我设想了类似的事情

void inline gate_wait(volatile int *gate)
{
    if (*gate)
        while (futex(gate, FUTEX_WAIT, 1, 0, 0, 0) == EINTR)
            ;
}

int inline gate_open(volatile int *gate)
{
    *gate = 0;
    return futex(gate, FUTEX_WAKE, INT_MAX, 0, 0, 0);
}

void inline gate_close(volatile int *gate)
{
    *gate = 1;
}
Run Code Online (Sandbox Code Playgroud)

如果您确实在 futex 之上构建此“门”同步原语,则可能值得将其贡献给 Rusty Russell 的用户空间 futex 库。