【问题标题】:Thread-safe ring buffer for producers-consumer in CC中生产者-消费者的线程安全环形缓冲区
【发布时间】:2012-08-28 14:40:06
【问题描述】:

在 C 中,我有几个线程产生 long 值,一个线程消耗它们。因此,我需要一个以与Wikipedia implementation 类似的方式实现的固定大小的缓冲区,以及以线程安全方式访问它的方法。

在一般层面上,应满足以下条件:

  • 当添加到一个完整的缓冲区时,线程应该被阻塞(不会覆盖旧值)。
  • 消费者线程应该被阻塞,直到缓冲区满 - 它的工作有很高的固定成本,应该做尽可能多的工作。 (这是否需要双缓冲解决方案?)

我想使用一个尝试过的实现,最好来自一个库。有什么想法吗?


动机和解释:

我正在编写处理删除global references 在堆对象中保留为tags 的JNI 代码。

ObjectFree JVMTI 事件发生时,我得到一个long 标记,表示我需要使用DeleteGlobalRef 释放的全局引用。为此,我需要一个 JNIEnv 参考 - 获得它真的成本很高,所以我想缓冲请求并一次删除尽可能多的请求。

可能有很多线程接收ObjectFree事件,并且会有一个线程(我的)做引用删除。

【问题讨论】:

    标签: c data-structures buffer


    【解决方案1】:

    您可以使用单个缓冲区,在访问时使用互斥锁。您需要跟踪使用了多少元素。对于“信号”,您可以使用条件变量。生产者线程在将数据放入队列时触发的一种;这会释放消费者线程来处理队列,直到为空。另一个由消费者线程在清空队列时触发;这向任何阻塞的生产者线程发出信号以填充队列。对于消费者来说,我建议在释放锁之前尽可能地锁定队列并取出(避免过多的锁),特别是因为出队操作简单快速。

    更新
    一些有用的链接:
    * Wikipedia explanation
    * POSIX Threads
    * MSDN

    【讨论】:

      【解决方案2】:

      两种可能:

      a) malloc() 一个 *Buffer 结构,带有一个数组来保存一些 long 和一个索引 - 不需要锁定。让每个生产者线程 malloc 自己的 *Buffer 并开始加载它。当生产者线程填充最后一个数组位置时,将 *Buffer 排队到生产者-消费者队列中的消费者线程,并立即 malloc() 一个新的 *Buffer。消费者获取 *Buffers 并处理它们,然后释放它们,(或将它们排在其他地方,或将它们推回池中以供生产者重用)。这避免了缓冲区本身的任何锁定,只留下 P-C 队列上的锁定。问题是,仅偶尔生成其 long 的生产者将不会处理他们的数据,直到他们的 *Buffer 被填满,这可能需要一些时间,(在这样的线程中,你可以在数组满之前推出 Buffer。

      b) 声明一个带有数组的 Buffer 结构来保存一些 long 和一个索引。使用 mutex/futex/CS 锁进行保护。 malloc() 只是一个共享的 *Buffer 并让所有线程获得锁,推动它们的长并释放锁。如果一个线程推入最后一个数组位置,则将 *Buffer 排队到生产者-消费者队列上的消费者线程,立即 malloc 一个新的 *Buffer 然后释放锁。消费者获取 *Buffers 并处理它们,然后释放它们,(或将它们排在其他地方,或将它们推回池中以供生产者重复使用)。

      【讨论】:

      • 您好,谢谢,不幸的是,我的 C 语言还不够好,无法知道您的答案是否真的适用于 C - 它似乎适用于 C++。你能澄清一下吗?
      • 哎呀!!!!!!!!!将在编辑中用 'struct' 代替 'class'、'malloc()' 代替 'new'、'free()' 和 delete()。我的坏:((
      【解决方案3】:

      您可能需要考虑条件。看看这段消费者代码:

      while( load == 0 )
          pthread_cond_wait( &notEmpty, &mutex );
      

      它的作用是检查负载(存储列表中元素数量的位置)是否为零,如果为零,它将等到生产者生成新项目并将其放入列表中.
      您应该为生产者实现相同的条件(当它想要将项目放入完整列表时)

      【讨论】:

        猜你喜欢
        • 2015-08-26
        • 2017-04-07
        • 2019-01-17
        • 2011-02-15
        • 1970-01-01
        • 1970-01-01
        • 2011-03-21
        • 2019-06-13
        • 1970-01-01
        相关资源
        最近更新 更多