csci4061/lab10-code/pthreads_picalc_mutex.c
Michael Zhang 041f660ccd
f
2018-01-29 17:28:37 -06:00

60 lines
2.1 KiB
C

// Working version of threaded picalc. Uses a mutex to lock the global
// variable total_hits so that one thread accesses it at a time. This
// version is inefficient due to the busy waiting and contention
// associated with mutex locking.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
// Global variables shared by all threads
int total_hits=0;
int points_per_thread = -1;
pthread_mutex_t lock;
void *compute_pi(void *arg){
long thread_id = (long) arg;
unsigned int rstate = 123456789 * thread_id; // give each thread its own starting point
for (int i = 0; i < points_per_thread; i++) {
double x = ((double) rand_r(&rstate)) / ((double) RAND_MAX);
double y = ((double) rand_r(&rstate)) / ((double) RAND_MAX);
if (x*x + y*y <= 1.0){
pthread_mutex_lock(&lock); // lock global variable
total_hits++; // update
pthread_mutex_unlock(&lock); // unlock global variable
}
}
return NULL;
}
int main(int argc, char **argv) {
if(argc < 2){
printf("usage: %s <num_samples> [num_threads]\n",argv[0]);
printf(" num_samples: int, how many sample points to try, higher gets closer to pi\n");
printf(" num_threads: int, number of threads to use for the computation, default 4\n");
return -1;
}
int npoints = atoi(argv[1]); // number of samples
int num_threads = argc>2 ? atoi(argv[2]) : 4; // number of threads
points_per_thread = npoints / num_threads; // init global variables
pthread_mutex_init(&lock, NULL); // create a lock
pthread_t threads[num_threads]; // track each thread
for(long p=0; p<num_threads; p++){ // launch each thread
pthread_create(&threads[p],NULL,compute_pi, (void *) (p+1));
}
for(int p=0; p<num_threads; p++){ // wait for each thread to finish
pthread_join(threads[p], (void **) NULL);
}
pthread_mutex_destroy(&lock); // get rid of the lock
double pi_est = ((double)total_hits) / npoints * 4.0;
printf("npoints: %8d\n",npoints);
printf("hits: %8d\n",total_hits);
printf("pi_est: %f\n",pi_est);
}