重用相同的线程

时间:2012-11-14 03:46:26

标签: c multithreading

我正在编写一个赋值程序,它使用线程在两个给定数组之间实现矩阵乘法。

我必须给出我想用作命令行参数的线程数,如果它们的数量小于第一个数组的行数,则重复使用相同的线程,直到整个作业完成。< / p>

我已经设法让它工作但只为数组的每一行使用一个线程。 例如,如果a具有5x5乘法并且使用少于5个线程,则会产生分段错误,这是有道理的。

我的问题是:如何在此线程完成其工作后重用一个线程? 在前面的例子中,我的意思是,如果我想使用2个线程作为5x5,我的程序应该像这样工作:

主题1-&gt;第1行

主题2-&gt;第2行

主题2-&gt;第3行

主题1-&gt;第4行

1 个答案:

答案 0 :(得分:3)

你有几种可能性,但主要的想法是你必须监控线程以检测他们何时完成工作,并且有办法知道是否还有一些事情要做。

首先想到的是拥有一个专用线程来跟踪所有正在运行的线程,并在完成后回收它们。但是为了做到这一点,你需要一种让线程同步的机制,这可以使用信号量或互斥或消息来实现,但如果你不需要它就可能只是为了那个目的而编码很麻烦。

第二种方式只是要求他们回收自己,因为他们知道什么时候完成。在许多其他语言中,有一种称为continuation的机制,它可以让你完全相同,但由于我们正在处理C,我们需要手动完成。幸运的是,这里的延续实际上只是一项任务。

所以调用continuation的机制实际上只是一个函数,它首先运行由线程执行的任务,然后是:

  • 检查任务列表。必须在设置时填写此任务列表,其中包含任务需要完成的所有工作,
  • 将线程添加到可用线程的队列中,必须由其他线程再次检查并重新分配新任务,

显然,第一个选项会更简单,在你的情况下,你已经知道在设置时需要做什么,所以你的设置功能可以填充任务列表,然后根据需要启动任意数量的线程,让他们自己做回收。

这是一个你可以开始的简单骨架:

 typedef struct {
    /* task related data */
 } task_t;

 // basic list structure
 typedef struct {
   list_t *next;
   void *data; // here app specific data
 } list_t;

 list_t task_list; // your task list

 // a few operators to manipulate a list
 // implementation must use a mutex to avoid race conditions
 void list_push(list *l, void *data);
 void *list_pop(list *l);


 // thread function

 void do_task(task_t *task){
     while (task) {
       run_task(task); // that would be the matrix related function
       task = list_pop(&task_list);
 }

 // here a simple define for the number of threads
 // you might want to check the number of available cores instead

 #define MAX_THREAD_COUNT 4 

 int main() {

   pthread_t threads[MAX_THREAD_COUNT];

   setup_task_list();  // push all the work that must be done in the list
   int i;
   for (i = 0; i < MAX_THREAD_COUNT; i++) {
      pthread_create(threads + i, NULL, do_task, list_pop(&task_list));
   }

   // here wait for all the threads, or detach them

 }

这是你可以做的基本概要,应该让你开始。 SO处理C链表时有几个问题。这里必须同步,不应阻止,并在空时返回NULL