You are on page 1of 8

Operating system

Lab 5
Full name: Trịnh Mạnh Hùng
Student id: 1952740

5. Exercises
Problem 1.

Assume that there is 100000 $ in a couple’s bank account.

Concurrently, the husband calls the withdraw() function and the wife calls deposit() function:

withdraw() will withdraw 20000$ and deposit() will deposit 30000$

There will be 3 possible outcomes we could get:

 Commands in function withdraw() runs before those in deposit():


- withdraw(): money = 100 000 – 20 000 = 80 000 $
- deposit(): money = 80 000 + 30 000 = 110 000 $
 Commands in function withdraw() runs after those in deposit():
- Deposit(): money = 100 000 + 30 000 = 130 000 $
- Withdraw(): money = 130 000 – 20 000 = 110 000 $
 Commands in function withdraw() runs with those in deposit():
- Withdraw(): money = 100 000 + 30 000 = 130 000 $ (but the result haven’t been updated
yet)
- Deposit(): money = 100 000 – 20 000 = 80 000 $ (final result)
Or
- Deposit(): money = 100 000 – 20 000 = 80 000 $ (but the result haven’t been updated yet)
- Withdraw(): money = 100 000 + 30 000 = 130 000 $ (final result)

As we can see, the third outcome is unexpected.

Solution for avoiding unexpected results: we have to use lock whenever one thread is accessing the
critical part, the other threads have to wait for their turn. As a result, there is no race condition.

Problem 2.
Code of nosynch.c:

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <pthread.h>
#include <unistd.h>
#define NUM_THREADS 3
#define TCOUNT 100
#define COUNT_LIMIT 20

int count = 10;

void *inc_count(void *tid) {
    int i;
    long my_id = (long)tid;
    for(i= 0; i < TCOUNT; ++i) {
        count++;
        if(count == COUNT_LIMIT) {
            printf("inc_count(): thread %ld, count = %d, threshold reached. coun
tlimit= %d \n", my_id, count, COUNT_LIMIT);
            printf("Just sent signal \n");
        }
        printf("inc_count(): thread %ld, count = %d, uncloking mutex\n", my_id, 
count);
        sleep(1);
    }
    pthread_exit(NULL);
}

void *watch_count(void *tid) {
    long my_id = (long) tid;
    printf("Starting watch_count(): thread %ld\n", my_id);
    while(count < COUNT_LIMIT) {
        printf("watch_count(): thread %ld, count = %d, waiting...\n", my_id, cou
nt);
        printf("watch_count(): thread %ld. Condition signal received. Count = %d
\n", my_id, count);
        printf("watch_count(): thread %ld Updating the count value...\n", my_id)
;
        count+= 80;
        printf("watch_count(): thread %ld count now = %d\n", my_id, count);
    }
    printf("watch_count(): thread %ld. Unlocking mutex. \n", my_id);
    
    pthread_exit(NULL);
}

int main() {
    int i, rc;
    pthread_t p1, p2, p3;
    long t1 = 1, t2 = 2, t3 = 3;
    //pthread_attr_t attr;

    printf("main: begin\n");
    
    pthread_create(&p1, NULL, watch_count, (void *)t1);
    pthread_create(&p2, NULL, inc_count, (void *)t2);
    pthread_create(&p3, NULL, inc_count, (void *)t3);
    rc = pthread_join(p1, NULL); assert(rc == 0);
    rc = pthread_join(p2, NULL); assert(rc == 0);
    rc = pthread_join(p3, NULL); assert(rc == 0);
    
    printf("main: finish, final count = %d\n", count);
    pthread_exit(NULL);
    return 0;
}

*Remarks about the displayed outputs when executing these two programs nosynch.c and
cond_usg.c:

 cond_usg.c: because race condition is solved, therefore the result will always be 290.
 nosynch.c: The result can be 290, when process 1 run first, or 210 when process 1 run
after process 2 or 3, ... We can see that the result depends on the order of each thread
runs.
Problem 3.

Code:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
#include <math.h>
#include <time.h>
#define NUM_OF_THREADS 4

double total_in_circle = 0;

pthread_mutex_t count_mutex;

void *cal1(void* tid) {
    
    int *n = (int *)tid;
    double * count = (double *)malloc(sizeof(double));
    *count = 0;
    //printf("so: %d\n", *n);
    pthread_mutex_lock(&count_mutex);
    for(int i = 0; i < *n; ++i) {
        double rand_x = (double) rand()/RAND_MAX;
        double rand_y = (double) rand()/RAND_MAX;
        double z = rand_x * rand_x + rand_y * rand_y;
        if(z <= 1) {
            total_in_circle += 1;
        }
    }
    pthread_mutex_unlock(&count_mutex);
    //printf("%d, %f\n", *n, *count);
    pthread_exit(NULL);
}

int main(int argc, char* argv[]) {
    srand(time(NULL));

    if(argc != 2) {
        printf("Wrong format!\nUsage: ./pi_multi-thread numberOfPoints\n");
        return 1;
    }

    void * result;
    int numOfPoints = atoi(argv[1]);
    if(numOfPoints < 0) {
        printf("numberOfPoints: %d must >= 0\n", numOfPoints);
        return -1;
    }
    int phandu = numOfPoints % NUM_OF_THREADS, 
        thuong = (numOfPoints/NUM_OF_THREADS);
    int rc; 
    pthread_mutex_init(&count_mutex, NULL);
    // request time
    clock_t begin = clock();
    
    pthread_t thread[NUM_OF_THREADS+1];
    for(int i= 0; i <= NUM_OF_THREADS; ++i) {
        if(i == NUM_OF_THREADS) {
            rc = pthread_create(&thread[i], NULL, cal1, &phandu);
            if(rc) {
                printf("ERROR! pthread_create() is %d\n", rc);
                exit(-1);
            }
        }
        else {
            rc = pthread_create(&thread[i], NULL, cal1, &thuong);
            if(rc) {
                printf("ERROR! pthread_create() is %d\n", rc);
                exit(-1);
            }
        }
        pthread_join(thread[i], NULL);
    }
    clock_t end = clock();
    double time_spent = (double)(end-begin)/ CLOCKS_PER_SEC;
    
    //ket thuc chuong trinh
    printf("Value for Pi: %f\n", 4.0*(total_in_circle/numOfPoints));
    printf("Time spent is: %f\n", time_spent);
    pthread_mutex_destroy(&count_mutex);
    pthread_exit(0);
    return 0;
}

Result:

Compared to the previous result in lab 3:

You might also like