2

I am trying tu calculate value of PI. I have multiple threads that are calculating PI. If difference between my PI and original PI is smaller than 0.0001, I want to send signal to other thread and finish threads. The other thread (that received signal) prints out the value of my PI.

I wrote program, but sometimes it works correctly, sometimes not :) Can anyone help me?

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define N_THR 3

double ns=0;
double zs=0;
double moj_pi=0;

int count=0;
double diff=100;
pthread_mutex_t count_mutex;
pthread_cond_t count_cv;



void *watch_count(void *t){
    pthread_mutex_lock(&count_mutex);
    while (diff>=0.0001) {
            pthread_cond_wait(&count_cv, &count_mutex);
            printf("Calculated PI: %f.\n", moj_pi);
    }
    pthread_mutex_unlock(&count_mutex);
    pthread_exit(NULL);
}


void *inc_count(void *t){
    while(diff>=0.0001){
        double x = ((double) rand()) / RAND_MAX;
        double y = ((double) rand()) / RAND_MAX;
        pthread_mutex_lock(&count_mutex);
        ns++;
        if (x*x + y*y <=1){
            zs++;
        }
        moj_pi=4* zs / ns;
        printf("PI: %f\n",moj_pi);
        diff=M_PI - moj_pi;
        if (diff<0)
            diff=0-diff;
        printf("Difference: %f\n",diff);
        if (diff <0.0001){
            pthread_cond_signal(&count_cv);
        }
        pthread_mutex_unlock(&count_mutex);
    }
    pthread_exit(NULL);
}



int main(){
    int i;
    pthread_t id[N_THR];
    pthread_attr_t attr;
    pthread_mutex_init(&count_mutex, NULL);
    pthread_cond_init(&count_cv, NULL);
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

    pthread_create(&id[0], &attr, watch_count, (void *)1);
    for (i=1;i<N_THR;i++)
        pthread_create(&id[i], &attr, inc_count, (void *)(i+1));

    for (i=0;i<N_THR;i++)
        pthread_join(id[i], NULL);


    pthread_attr_destroy(&attr);
    pthread_mutex_destroy(&count_mutex);
    pthread_cond_destroy(&count_cv);
    pthread_exit(NULL);
}
3
  • 1
    What do you mean by "but sometimes it works correctly, sometimes not"? What have you tried? Commented Dec 1, 2014 at 17:50
  • Well. When Pi is calculated close enough, it calls watch_count. But sometimes when calculated PI is printed, program doesn't stop, but it keeps calculating Pi. I want that when Pi is close enough, the program stops. Commented Dec 1, 2014 at 17:59
  • Be careful when casting int to void * (when passing (void *)(i+1)), if their respective sizes don't match it could become a problem. Commented Dec 1, 2014 at 18:14

1 Answer 1

2

You are using variable diff from multiple threads without it being protected by mutex always.

Also, as said in man page of rand():

The function rand() is not reentrant or thread-safe, since it uses hidden state that is modified on each call


At a 2nd glance, your problem is, diff may change after you test it in loop, and before you lock the mutex. You need to rethink your locking logic a bit to avoid this race condition.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks a lot. I moved mutex outside of while loop and now it works fine! Thanks
@JernejBevk Note that you need to do the actual calculation mutex unlocked, otherwise your threads will not run concurrently (which makes having threads somewhat pointless). If threads do possibly overlapping work, then after calculation and re-locking mutex you need to check if result of calculation is still valid, so you do not overwrite better result from other thread.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.