c - Multithreaded program outputs different results every time it runs -
i have been trying create multithreaded program calculates multiples of 3 , 5 1 999 can't seem right every time run different value think might have fact use shared variable 10 threads have no idea how around that. program work if calculate multiples of 3 , 5 1 9.
#include <stdlib.h> #include <stdio.h> #include <omp.h> #include <string.h> #define num_threads 10 #define max 1000 //finds multiples of 3 , 5 , sums of multiples int main(int argc, char ** argv) { omp_set_num_threads(10);//set number of threads used in parallel loop unsigned int nums[1000] = { 0 }; int j = 0; #pragma omp parallel { int id = omp_get_thread_num();//get thread id int i; for(i = id + 1;i < max; i+= num_threads) { if( % 5 == 0 || % 3 == 0) { nums[j++] = i;//store multiples of 3 , 5 in array sum later } } } int = 0; unsigned int total; for(i = 0; nums[i] != 0; i++)total += nums[i];//add multiples of 3 , 5 printf("total : %d\n", total); return 0; }
this typical thread synchronization issue. need using kernel synchronization object sake of atomicity of desired operation (incrementing value of variable j in case). mutex, semaphore or event object depending on operating system you're working on. whatever development environment is, provide atomicity, fundamental flow logic should following pseudo-code:
{ lock(kernel_object) // ... // critical operation (increment variable j in case) // ++j; // ... unlock(kernel_object) }
if you're working on windows operating system, there special synchronization mechanisms provided environment (i.e: interlockedincrement or createcriticalsection etc.) if you're working on unix/linux based operating system, can use mutex or semaphore kernel synchronization objects. synchronization mechanism stem concept of semaphores invented edsger w. dijkstra in begining of 1960's.
here's basic examples below:
linux
#include <pthread.h> pthread_mutex_t g_mutexobject = pthread_mutex_initializer; int main(int argc, char* argv[]) { // ... pthread_mutex_lock(&g_mutexobject); ++j; // incrementing j atomically pthread_mutex_unlock(&g_mutexobject); // ... pthread_mutex_destroy(&g_mutexobject); // ... exit(exit_success); }
windows
#include <windows.h> critical_section g_csobject; int main(void) { // ... initializecriticalsection(&g_csobject); // ... entercriticalsection(&g_csobject); ++j; // incrementing j atomically leavecriticalsection(&g_csobject); // ... deletecriticalsection(&g_csobject); // ... exit(exit_success); }
or simply:
#include <windows.h> long volatile g_j; // our little j must volatile in here int main(void) { // ... interlockedincrement(&g_j); // incrementing j atomically // ... exit(exit_success); }