线程调度C.

时间:2010-04-06 02:30:23

标签: c multithreading pthreads

 #include <pthread.h>
 #include <stdio.h>
 #include <stdlib.h>
 #define NUM_THREADS  4
 #define TCOUNT 5
 #define COUNT_LIMIT 13

 int     done = 0;
 int    count = 0;
 int     thread_ids[4] = {0,1,2,3};
 int thread_runtime[4] = {0,5,4,1};
 pthread_mutex_t count_mutex;
 pthread_cond_t count_threshold_cv;

 void *inc_count(void *t)
 {
   int i;
   long my_id = (long)t;
   long run_time = thread_runtime[my_id];
   if (my_id==2 && done==0) {
     for(i=0; i<5 ; i++) {
       if (i==4) {
         done = 1;
       }
       pthread_mutex_lock(&count_mutex);
       count++;

       if (count == COUNT_LIMIT) {
         pthread_cond_signal(&count_threshold_cv);
         printf("inc_count(): thread %ld, count = %d  Threshold reached.\n",
           my_id, count);
       }
       printf("inc_count(): thread %ld, count = %d, unlocking mutex\n", my_id, count);
       pthread_mutex_unlock(&count_mutex);
     }
   }

   if (my_id==3 && done==1) {
     for(i=0; i< 4 ; i++) {
       if (i==3) {
         done = 2;
       }
       pthread_mutex_lock(&count_mutex);
       count++;

       if (count == COUNT_LIMIT) {
         pthread_cond_signal(&count_threshold_cv);
         printf("inc_count(): thread %ld, count = %d  Threshold reached.\n",
           my_id, count);
       }
       printf("inc_count(): thread %ld, count = %d, unlocking mutex\n", my_id, count);
       pthread_mutex_unlock(&count_mutex);
     }
   }

   if (my_id==4 && done==2) {
     for(i=0; i<8; i++) {
       pthread_mutex_lock(&count_mutex);
       count++;
       if (count == COUNT_LIMIT) {
         pthread_cond_signal(&count_threshold_cv);
         printf("inc_count(): thread %ld, count = %d  Threshold reached.\n",
           my_id, count);
       }
       printf("inc_count(): thread %ld, count = %d, unlocking mutex\n", my_id, count);
       pthread_mutex_unlock(&count_mutex);
     }
   }
   pthread_exit(NULL);
 }

 void *watch_count(void *t)
 {
   long my_id = (long)t;

   printf("Starting watch_count(): thread %ld\n", my_id);
   pthread_mutex_lock(&count_mutex);
   if (count<COUNT_LIMIT) {
     pthread_cond_wait(&count_threshold_cv, &count_mutex);
     printf("watch_count(): thread %ld Condition signal received.\n", my_id);
     count += 125;
     printf("watch_count(): thread %ld count now = %d.\n", my_id, count);
   }
   pthread_mutex_unlock(&count_mutex);
   pthread_exit(NULL);
 }

 int main (int argc, char *argv[])
 {
   int i, rc;
   long t1=1, t2=2, t3=3, t4=4;
   pthread_t threads[4];
   pthread_attr_t attr;

   pthread_mutex_init(&count_mutex, NULL);
   pthread_cond_init (&count_threshold_cv, NULL);
   pthread_attr_init(&attr);
   pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_JOINABLE);
   pthread_create(&threads[0], &attr, watch_count, (void *)t1);
   pthread_create(&threads[1], &attr, inc_count, (void *)t2);
   pthread_create(&threads[2], &attr, inc_count, (void *)t3);
   pthread_create(&threads[3], &attr, inc_count, (void *)t4);

   for (i=0; i<NUM_THREADS; i++) {
     pthread_join(threads[i], NULL);
   }
   printf ("Main(): Waited on %d  threads. Done.\n", NUM_THREADS);

   pthread_attr_destroy(&attr);
   pthread_mutex_destroy(&count_mutex);
   pthread_cond_destroy(&count_threshold_cv);
   pthread_exit(NULL);
 }

所以这段代码创建了4个线程。线程1跟踪计数值,而另一个3增加计数值。运行时间是线程递增计数值的次数。我有一个完成值,允许第一个线程首先递增计数值,直到它的运行时间结束..所以它就像先到先服务。

我的问题是:有更好的方法来实现吗?我读过有关SCHED_FIFO或SCHED_RR的内容。我想我不知道如何在这段代码中实现它们,或者它是否可以

2 个答案:

答案 0 :(得分:2)

如果我正确地理解了这个问题,那么你正试图产生一种管道,其中下一个线程会在前一个线程停止的地方找到。在这种情况下,最干净的解决方案是使用二进制信号量

假设您有四个主题。创建四个信号量,初始值为{1, 0, 0, 0}。为每个线程分配信号量,并在开始时让每个线程down为其信号量,并在链中为up 提供下一个信号量(模数线程数)。启动所有线程 - 第一个线程立即获取其信号量,执行其工作,其他线程阻塞其信号量。第一个线程完成工作,up是下一个信号量,因此唤醒下一个线程,然后循环到开头等等。

我认为你提到的实时调度类与手头的问题无关。

关于您的代码的一些注意事项:

  • 不受锁定保护的变量(表示线程之间的状态变化(如此处为done))必须为 volatile ,因此编译器不会将它们优化出循环。
  • 您可以使用线程函数参数将更复杂的信息传递给线程,比如指向结构的指针。
  • 您总是希望在循环中调用pthread_cond_wait ,其中循环条件会检查您等待的内容。这是为了避免spurious wakeups
  • 你总是希望在锁定之外调用pthread_cond_signal,或者在解锁前最后一次调用pthread。这是为了避免等待线程中浪费的唤醒/睡眠周期 - 它们唤醒,发现互斥锁仍然锁定,再次阻塞(睡眠)。
  • 避免许多线程在同一个锁上竞争,这会导致thundering herd问题。
  • 始终检查{{1}}来电的返回值。

希望这有帮助。

答案 1 :(得分:1)

SCHED_FIFO和SCHED_RR是实时调度类。它们不适用于普通代码。您应该可以使用pthread互斥锁执行大部分操作。