多线程单读者单写入器fifo队列

Fir*_*cer 8 c++ linux windows multithreading message-queue

我需要一个队列来将消息从一个线程(A)传递到另一个线程(B),但是我找不到真正做到我想要的东西,因为它们通常允许添加一个项目失败,这种情况在我的情况下由于需要处理消息,因此线程真的无法停止并等待备用空间,因此非常致命.

  • 只有线程A添加项目,只有线程B读取它们
  • 线程A必须永远不会阻塞,但线程B不是性能关键,所以它可以
  • 添加项必须始终成功,因此队列不能具有大小上限(缺少系统内存不足)
  • 如果队列为空,则线程B应该等待,直到有一个要处理的项目

Ste*_*sop 7

以下是如何在C++中编写无锁队列:

http://www.ddj.com/hpc-high-performance-computing/210604448

但是当你说"线程A必须阻止"时,你确定这是要求吗?Windows不是实时操作系统(在正常使用中也不是linux).如果您希望线程A能够使用所有可用的系统内存,那么它需要分配内存(或等待其他人执行).如果读取器和写入器都采用进程内锁(即非共享互斥锁)来操作列表,则操作系统本身无法提供比您所拥有的更好的时序保证.添加消息的最坏情况是必须转到操作系统才能获得内存.

简而言之,这些你不喜欢的队列有一个固定容量的原因 - 这样他们就不必在所谓的低延迟线程中分配内存.

因此,无锁代码通常会减少阻塞,但由于内存分配不能保证,并且使用互斥锁的性能不应该是那么糟糕,除非你有一个真正庞大的事件流进程(比如,您正在编写网络驱动程序,而消息是传入的以太网数据包).

所以,在伪代码中,我要尝试的第一件事是:

Writer:
    allocate message and fill it in
    acquire lock
        append node to intrusive list
        signal condition variable
    release lock

Reader:
    for(;;)
        acquire lock
            for(;;)
                if there's a node
                    remove it
                    break
                else
                   wait on condition variable
                endif
            endfor
        release lock
        process message
        free message
    endfor
Run Code Online (Sandbox Code Playgroud)

只有当这证明在编写器线程中引入了不可接受的延迟时,我才能使用无锁代码(除非我碰巧有一个合适的队列已经存在).