C中的多写线程安全队列 [英] Multiple-writer thread-safe queue in C

查看:26
本文介绍了C中的多写线程安全队列的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 pthreads 开发一个多线程 C 应用程序.我有一个写入数据库的线程(数据库库只能在单个线程中安全使用),还有几个线程正在收集数据,处理它,然后需要将结果发送到数据库线程进行存储.我在提到过在 C 中创建一个多写入器安全队列是可能的",但是我看到的每个地方都只是说它对于这个例子来说太复杂了"并且仅仅演示了一个单写入器安全队列.

I am working on a multi-threaded C application using pthreads. I have one thread which writes to a a database (the database library is only safe to be used in a single thread), and several threads which are gathering data, processing it, and then need to send the results to the database thread for storage. I've seen in mentioned that it is "possible" to make a multiple-writer safe queue in C, but every place I see this mentioned simply says that it's "too complicated for this example" and merely demonstrates a single-writer safe queue.

我需要以下东西:

  • 高效插入和移除.我假设像任何其他队列一样,O(1) 入队和出队是可能的.
  • 动态分配的内存,即链接结构.我不需要对队列的大小有任意限制,所以数组真的不是我想要的.
  • Efficient insertion and removal. I would assume that like any other queue O(1) enqueueing and dequeueing is possible.
  • Dynamically allocated memory, i.e. a linked structure. I need to not have an arbitrary limit on the size of the queue, so an array really isn't what I'm looking for.

读取线程不应该在空队列上旋转,因为可能有几分钟的时间没有写入,大量写入的短时间爆发.

Reading threads should not spin on an empty queue, since there is likely to be minutes worth of time with no writes, with short bursts of large numbers of writes.

推荐答案

当然,有无锁队列.不过,根据您在评论中所说的,这里的性能并不重要,因为无论如何您都是在每次写入时创建一个线程.

Sure, there are lockless queues. Based on what you've said in comments, though, performance here is not at all critical, since you're creating a thread per write anyway.

因此,这是条件变量的标准用例.让自己成为一个包含互斥体、条件变量、链表(或循环缓冲区,如果你喜欢)和取消标志的结构:

So, this is a standard use case for a condition variable. Make yourself a struct containing a mutex, a condition variable, a linked list (or circular buffer if you like), and a cancel flag:

write:
    lock the mutex
    (optionally - check the cancel flag to prevent leaks of stuff on the list)
    add the event to the list
    signal the condition variable
    unlock the mutex

read:
   lock the mutex
   while (list is empty AND cancel is false):
       wait on the condition variable with the mutex
   if cancel is false:  // or "if list non-empty", depending on cancel semantics
       remove an event from the list
   unlock the mutex
   return event if we have one, else NULL meaning "cancelled"

cancel:
   lock the mutex
   set the cancel flag
   (optionally - dispose of anything on the list, since the reader will quit)
   signal the condition variable
   unlock the mutex

如果您使用带有外部节点的列表,那么您可能希望在互斥锁之外分配内存,以减少其持有时间.但是,如果您使用侵入式列表节点设计事件,那可能是最简单的.

If you're using a list with external nodes, then you might want to allocate the memory outside the mutex lock, just to reduce the time its held for. But if you design the events with an intrusive list node that's probably easiest.

如果在取消时将信号"更改为广播",您还可以支持多个阅读器(没有可移植的保证).虽然你不需要它,但它也并不真正花费任何东西.

you can also support multiple readers (with no portable guarantees for which one gets a given event) if in cancel you change the "signal" to "broadcast". Although you don't need it, it doesn't really cost anything either.

这篇关于C中的多写线程安全队列的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆