Currently I am learning POSIX threads on Linux. The following example is counting how many 3(int) there are in an integer array, which returns a correct answer on CentOS 6.5 but a wrong one on macOS 10.12.4.
#include <stdlib.h>
#include <semaphore.h>
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
#define thread_num 16
#define MB 1024 * 1024
int *array;
int length; //array length
int count;
int t; //number of thread
void *count3s_thread(void* id);
pthread_mutex_t myMutex;//create a mutex
int main()
{
//initialize mutex
if (pthread_mutex_init(&myMutex, NULL) != 0)
printf("Mutex init failed!n");
int i;
int tid[thread_num];
pthread_t threads[thread_num];
length = 64 * MB;
array = malloc(length * 4);
//initialize the array
//when i is an odd number, array[i] = 4
//when i is an even number, array[i] = 3
for (i = 0; i < length; i++)
array[i] = i % 2 ? 4 : 3;
for (t = 0; t < thread_num; t++)
{
count = 0;
tid[t]=t;
int err = pthread_create(&(threads[t]), NULL, count3s_thread,&(tid[t]) );
if (err)
{
printf("create thread error!n");
return 0;
}
}
for (t = 1; t < thread_num; t++)
pthread_join(threads[t], NULL);
printf("Total count= %d n",count);
pthread_mutex_destroy(&myMutex);
return 0;
}
void *count3s_thread(void* id)
{
//printf("id from count3s_thread = %dn", *(int *)id);
int length_per_thread = length / thread_num; //length of every thread
int start = *(int *)id * length_per_thread;
int i;
for (i = start; i < start + length_per_thread; i++)
{
if (array[i] == 3)
{
pthread_mutex_lock(&myMutex);
count++;
pthread_mutex_unlock(&myMutex);
}
}
return NULL;
}
The answer should be 64 * 1024 * 1024 / 2 = 67,108,864 / 2 = 33,554,432. But the answer on macOS is never right. I compile the code with the following options:
gcc mutex-demo.c -lpthread -o mutex-demo
I have tried solving the problem following this link. However, I still got a wrong answer having initialized pthread mutex. Did I miss something?
PS: I have tried either pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
or pthread_mutex_init( &mutex, NULL)
but the program running on macOS still returns a wrong answer.
Advanced thanks!
Advertisement
Answer
The line count = 0;
before the pthread_create
sets count
to 0
, so you reset the value of count
while the threads increment them. Remove this line. It probably worked on other systems, when the main thread finishes the pthread_create
before the threads starts counting.
I already mentioned it in the comments:
for (t = 1; t < thread_num; t++)
pthread_join(threads[t], NULL);
should be
for (t = 0; t < thread_num; t++)
// ^
pthread_join(threads[t], NULL);
otherwise you will not wait for the first thread to be done.