4

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

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

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

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


动机与解释:

我正在编写处理删除作为标记保存在堆对象中的全局引用的 JNI 代码。

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

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

4

3 回答 3

1

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

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

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

于 2012-08-28T19:23:26.177 回答
1

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

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

于 2012-08-28T16:06:00.550 回答
1

两种可能:

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

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

于 2012-08-28T18:32:29.793 回答