gpt4 book ai didi

c++ - posix 管道作为工作队列

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:31:16 28 4
gpt4 key购买 nike

我见过的工作队列的正常实现涉及互斥锁和条件变量。

消费者:

A) Acquires Lock
B) While Queue empty
Wait on Condition Variable (thus suspending thread and releasing lock)
C) Work object retrieved from queue
D) Lock is released
E) Do Work
F) GOTO A

制作人:

A) Acquires Lock
B) Work is added to queue
C) condition variable is signaled (potentially releasing worker)
D) Lock is released

我一直在浏览一些代码,我看到了一个使用 POSIX 管道的实现(我以前从未见过这种技术)。

消费者:

A) Do select on pipe (thus suspending thread while no work)
B) Get Job from pipe
C) Do Work
D) GOTO A

制作人:

A) Write Job to pipe.

由于生产者和消费者是同一个应用程序中的线程(因此它们共享相同的地址空间,因此它们之间的指针是有效的);作业作为工作对象(C++ 对象)的地址写入管道。所以所有必须从管道写入/读取的是一个 8 字节的地址。

我的问题是:

  • 这是一种常见的技术吗(我是否避开了它),优点/缺点是什么?

我的好奇心被激起了,因为管道技术不涉及任何可见的锁或信号(它可能隐藏在选择中)。所以我想知道这是否会更有效率?

编辑:

基于@Maxim Yegorushkin 回答中的评论。

实际上,此场景中的“生产者”涉及来自多个源的大量并行 IO。所以我怀疑原作者虽然非常希望这个线程在任何情况下都不会阻塞,但也不想在“Producer”线程中进行高成本的工作。

最佳答案

正如这里已经提到的那样,人们使用管道作为队列来避免阻塞非阻塞 I/O 线程中的条件变量(即处理多个套接字并阻塞 select 的线程)/epoll)。如果 I/O 线程阻塞在条件变量或互斥锁上,它就不能再进行非阻塞 I/O。

有人说写入管道涉及系统调用,并且当线程间事件量很大时可能会增加延迟。这仅适用于简单的基于管道的队列实现。

高级实现使用作业/事件的无锁链表,只有当第一个作业被添加到列表时,管道才会被写入以从阻塞的 epoll 中唤醒目标 I/O 线程调用(本质上是使用管道作为边缘触发的通知机制,而不是将指针传递给作业/事件)。因为唤醒线程需要几微秒,所以在此期间可能会有更多作业/事件发布到该线程的事件队列,但每个后续事件都不需要写入管道,直到稍后 I/O线程唤醒并消耗队列中的所有事件。此外,在较新的 Linux 内核中,可以使用更快的 eventfd 代替管道来唤醒 I/O 线程。

关于c++ - posix 管道作为工作队列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9911490/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com