c - 任务比较多的线程池

标签 c multithreading

我在C中创建了一个线程池。池中的每个线程执行完全相同的功能。多个生产者线程使用相当标准的 mutex/cond 方法将新数据放入该池的队列中。

新数据总是比较大,必须执行的处理量可能需要相当长的时间。每当我看到类似这样的实现时,工作人员都会在复制所需数据或执行请求的任务时锁定队列。在我的例子中,这些操作中的任何一个都可能需要一段时间,并且在此期间其他线程将被阻止访问队列。

我应该如何着手宣布一个特定的线程已经接受了一项任务,但与该任务相关的数据仍在使用中?向队列添加某种“进程中”标志并让工作线程在工作时解锁队列是否可行?

最佳答案

修改排队结构,让排队的只是一个指向待处理数据的指针。

当一个线程需要获取一个任务时,它获取互斥锁,获取下一个指向要执行的任务的指针,可能会删除指针的队列中副本,或者以其他方式确保其他线程不会处理什么它正在处理,然后释放互斥量(或发出条件或其他信号)。通过指针访问大块数据;只有一个线程有指针;它会在完成后进行清理,但它可以安全地运行,因为它知道没有其他线程正在处理相同的数据。

因此,您可以通过不在队列中使用大数据 block 来解决大数据 block 的问题——您使用小数据 block ,也就是指向大数据 block 的指针。

Currently my queue is a queue of pointers. However, I malloc a finite number of buffers at the beginning of the program. Correct me if I am wrong, but what you are suggesting is that I instead have the producer threads malloc memory as required, and have workers free it when they finish?

我并不是建议您让生产者使用 malloc() 而让消费者使用 free()

我的建议是组织队列,这样就不会出现生产者或消费者需要长时间锁定它的问题。但是,如果您的队列已经是指针队列,我首先不明白您是怎么遇到问题的。

这可能归结为术语——这是造成混淆的主要原因。

我想建议的是,有一列“等待处理的任务”。有时,那个队列是空的;然后消费者线程将在“队列不为空”的条件下等待,当生产者将任务添加到队列时,其中一个等待的消费者将被唤醒并接管运行新任务。但消费者的第一步只是将任务从“等待消费”队列中移除。

队列上的信息必须足以识别需要做什么——这可能只是指向“任务描述”的指针,其中包含指向要操作的数据存储位置的进一步指针。从队列中删除“任务描述”应该(必须)是一个快速、简单的操作(受互斥锁和条件保护)。一个给定的任务描述不会被多个线程同时访问它指向的数据不会被其他线程访问(一般情况下)。如果线程之间共享数据,则必须像往常一样协调对该共享数据的并发访问。

但关键的设计点是消费者线程在操作队列时花费最少的时间阻塞其他消费者线程或生产者线程。它获得对队列的访问权限,删除队列中的第一项,然后释放对队列的访问权限。然后它会继续处理需要完成的任务,而不会受到生产者或其他消费者的干扰。

同样,生产者线程准备任务描述并确保使用相关(预分配)缓冲区等——仔细处理缓冲区的获取等。但是当任务描述准备就绪时,生产者花费非常短的时间获取对队列的访问,将任务描述添加到队列,释放对队列的访问,发出“队列不为空”条件的信号。

关于c - 任务比较多的线程池,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30949871/

相关文章:

python - 用 Popen 模仿 glib.spawn 异步...

c - 两个数组 C 中的输出不正确

ruby-on-rails - 每个 RAILS_ENV 运行多个 delay_job 实例

iphone - 胎面 9 : EXC_BAD_ACCESS

c - 在没有 UAC 提示的情况下提高进程完整性

objective-c - 使用 GCD 等待条件

java - 有没有办法让线程知道它已经是 "interleaved"?

c - 如何在到达给定断点之前自动打印 GDB 中的每一行?

c - 如何在两个应用程序之间共享一个共享库(*.so)实例

带有链接列表的 C 程序最后崩溃