简体   繁体   中英

Counting a number in a list using pthreads.. C

I am having trouble getting using pthreads to count the number of 3's in a list. Using a serial version of my code works fine but trying to use pthread_create is giving me trouble. Currently the problem is that count3s_thread_2(int id) is not giving me the same value as the serial version. What do I need to change? PS, sorry for the mess. I am new to programming in C.

// Declares some global variables we will use throughout the
// program with all versions.
#define NUM_THREADS      4
int Length = 1000;
int array[1000];
int count;
long i;
pthread_mutex_t m;
pthread_t threads[NUM_THREADS];

void create_list(int *array)
{
   srand(time(NULL));
   for (i = 0; i < Length; i++)
   {
      int r = rand();
      r = (r % 10) + 1;
      array[i] = r;
   }
}

void* count3s(void* threadid)
{
   // This is the function that counts the number of threes for
   // the first threaded version.
   //int i = (intptr_t)threadid;
   int i = (intptr_t)threadid;
   long tid = (long)threadid;
   int length_per_thread = Length / NUM_THREADS;
   long start = tid * (long)length_per_thread;

   for (i = start; i < start + length_per_thread; i++)
   {
      if (array[i] == 3)
      {
         count++;
      }
   }
   pthread_exit(NULL);
}

void* count3s_v2(void* threadid)
{
   // This is the function that counts the number of threes for
   // the second threaded version.
   //int serial = count3s_serial();
   //printf("Number of threes: %d\n", serial);
   int i = (intptr_t)threadid;
   long tid = (long)threadid;
   int length_per_thread = Length / NUM_THREADS;
   long start = tid * (long)length_per_thread;

   for (i = start; i < start + length_per_thread; i++)
   {
      if (array[i] == 3)
      {
         pthread_mutex_lock(&m);
         count++;
         pthread_mutex_unlock(&m);
      }
   }
   pthread_exit(NULL);
}

int count3s_serial()
{
   // This is the serial version of count3s. No threads are
   // created and run separately from other threads.
       count = 0;

   for (i = 0; i < Length; i++)
   {
      if (array[i] == 3)
      {
         count++;
      }
   }

   return count;
}

int count3s_thread(int id)
{
   clock_t begin, end;
   double time_spent;

   begin = clock();
   //pthread_attr_init();
   for (i = 0; i < NUM_THREADS; i++)
   {
      pthread_create(&threads[i], NULL, count3s, (void *)i);
   }
   //pthread_attr_destroy();
   end = clock();
   time_spent = (double)(end - begin) / CLOCKS_PER_SEC;

   return count;
}

int count3s_thread_2(int id)
{
   clock_t begin, end;
   double time_spent;
   begin = clock();
   pthread_attr_init(&something);
   for (i = 0; i < NUM_THREADS; i++)
   {
      pthread_create(&threads[i], NULL, count3s_v2, (void *)i);
   }
   pthread_attr_destroy(&something);
   end = clock();
   time_spent = (double)(end - begin) / CLOCKS_PER_SEC;

   return count;
   //printf("Thread Version 2: Number of threes = %d\nThread Version 2: Time Spent = %f\n", count, time_spent);
}

int main()
{
   create_list(array);
   clock_t begin, end;
   double time_spent;

   for (i = 0; i < Length; i++)
   {
      printf("%d\n", array[i]);
   }

   // Beginning of serial version. Timer begins, serial version
   // is ran and after it's done, the timer stops.
   begin = clock();
   int serial = count3s_serial();
   end = clock();

   time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
   printf("Serial Version: Number of threes = %d\nSerial Version: Time Spent = %f\n", serial, time_spent);
   // End of serial version.
/*
*********************************************************************
*/
   // Beginning of first theaded version. Timer begins, first
   // threaded version is ran and after it's done, the timer stops.
   int the_thing = 0;
   count = 0;
   the_thing = count3s_thread(i);

   printf("Thread Version 1: Number of threes = %d\nThread Version 1: Time Spent = %f\n", the_thing, time_spent);
   // End of first threaded version.
/*
*********************************************************************
*/
   // Beginning of second theaded version. Timer begins, second
   // threaded version is ran and after it's done, the timer stops.
   int the_other_thing = 0;
   count = 0;
   the_other_thing = count3s_thread_2(i);

   printf("Thread Version 2: Number of threes = %d\nThread Version 2: Time Spent = %f\n", the_other_thing, time_spent);

   pthread_exit(NULL);
}

The problem is that you spawn the threads but don't wait for them to finish before printing the result. Both thread versions have the same problem. Use pthread_join to wait for the threads to exit or implement some other synchronisation for parent to know when the threads have completed their work.

For example, add the following block of code to the end of both count3s_thread and count3s_thread_2 . It will wait for the threads to complete before printing the result. NOTE: You must add it to both functions (even though you are ok for the first one to have the wrong count). Otherwise when you run the second threading version the first set of threads are likely to still be executing and will mess up the global count .

for (i = 0; i < NUM_THREADS; i++) {
    pthread_join(threads[i], NULL);
}

Okay, mucked around with your code and got it to compile. You aren't waiting for your threads to return before you announce the result. You need to pthread_join() each of your threads in count3s_thread() before it returns.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM