The program in question is this one:
#include <pthread.h>
#include <stdio.h>
#define NUM_LOOPS 500000000
long long sum = 0;
/* Add or subtract the offset specified in arg from the sum NUM_LOOPS times */
void* counting_function(void* arg) {
int offset = *(int*)arg;
for (int i = 0; i < NUM_LOOPS; i++) {
sum += offset;
}
pthread_exit(NULL);
}
int main(void) {
// Spawn the threads
pthread_t id1;
int offset1 = 1;
pthread_create(&id1, NULL, counting_function, &offset1);
pthread_t id2;
int offset2 = -1;
pthread_create(&id2, NULL, counting_function, &offset2);
// Wait for threads to finish
pthread_join(id1, NULL);
pthread_join(id2, NULL);
printf("Sum = %lld\n", sum);
return 0;
}
I have a global variable long long sum = 0
and a macro for NUM_LOOPS 500000000
that specifies the number to add up to.
The function void* counting_function(void* arg)
just adds the offset to sum NUM_LOOPS
times.
If I were to run this without threads but calling the functions one after another like this
// sum is 0
counting_function(1);
// sum is now equal to 500000000
countnig_function(-1);
// sum is now equal to 0
I would get the correct answer, 0.
But when using threads, I get a non-zero answer, different every time.
gcc -Wall -Wextra -Werror -std=c99 -pthread count.c && ./a.out
Sum = 40098157
./a.out
Sum = 303575386
It seems to me that in whatever order you add or subtract 1 from a number, if the total amount of summations and subtractions is the same, then the answer should always be 0.
For example, let's say that NUM_LOOPS = 10. The first thread adds 1 three times in a row, then the second thread subtracts 1 two times in a row. The sum is now going to be equal to 1. Then the first thread does the remaining seven additions, so sum is equal to 8 and then the second thread subtracts the final eight times. The sum is 0.
How can you possibly get an answer that is different than 0? Having an answer different than 0 would mean that one of the two threads added or subtracted more than the specified amount in NUM_LOOPS.
The problem can be solved by adding mutual exclusion to the critical section sum += offset;
inside the counting function, but I can't seem to figure out why it wouldn't work without mutex.
What am I missing?