0

Problem: I have to increment x1 and x2 variable which should be done by separate threads and next increment of both variables should not be called until previous increment of both variable is not completed.

Problem:

x1 =  0;  x2 = 0;

x1++; and x2++; should run parallel on different threads and wait for printing.
should print: x1 = 1 and x2 = 1 
x1++; and x2++; should run parallel on different threads and wait for printing.
should print: x1 = 2 and x2 = 2 
x1++; and x2++; should run parallel on different threads and wait for printing.
should print: x1 = 3 and x2 = 3 
x1++; and x2++; should run parallel on different threads and wait for printing.
should print: x1 = 4 and x2 = 4
    …
    …
    …
x1++; and x2++; should run parallel on different threads and wait for printing.
should print: x1 = 10 and x2 = 10

close the threads

Proposed Solution Using pthread condition: Initialize 4 mutexes and 4 condition variables, and use 2 mutextes to lock main function and rest each for each thread. Both of the threads will wait for the main function to pass the condtion signal to invoke them and after calculation, they are passing back the signal to main thread to move further. sleep of 1 sec is provided asking the threads to invoke properly and get ready to recieve and return signal after calculation.

Pthread Condition Code:

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

    pthread_t pth1,pth2;
    //Values to calculate
    int x1 = 0, x2 = 0;

    pthread_mutex_t m1, m2, m3, m4 = PTHREAD_MUTEX_INITIALIZER;
    pthread_cond_t c1, c2, c3, c4 = PTHREAD_COND_INITIALIZER;

    void *threadfunc1(void *parm)
    {
        pthread_mutex_lock(&m1);
        for (;;) {
            pthread_cond_wait(&c1, &m1);
            x1++;
            pthread_mutex_lock(&m3);
            pthread_cond_signal(&c3);
            pthread_mutex_unlock(&m3);
        }
        pthread_mutex_unlock(&m1);
        return NULL ;
    }
    void *threadfunc2(void *parm)
    {
        pthread_mutex_lock(&m2);
        for (;;) {
            pthread_cond_wait(&c2, &m2);
            x2++;
            pthread_mutex_lock(&m4);
            pthread_cond_signal(&c4);
            pthread_mutex_unlock(&m4);
        }
        pthread_mutex_unlock(&m2);
        return NULL ;
    }

    int main () {
        pthread_create(&pth1, NULL, threadfunc1, "foo");
        pthread_create(&pth2, NULL, threadfunc2, "foo");
        sleep(1);
        int loop = 0;
        pthread_mutex_lock(&m3);
        pthread_mutex_lock(&m4);
        while (loop < 10) {
            // iterated as a step
            loop++;
            printf("Initial   : x1 = %d, x2 = %d\n", x1, x2);
            pthread_mutex_lock(&m1);
            pthread_cond_signal(&c1);
            pthread_mutex_unlock(&m1);
            pthread_mutex_lock(&m2);
            pthread_cond_signal(&c2);
            pthread_mutex_unlock(&m2);
            pthread_cond_wait(&c3, &m3);
            pthread_cond_wait(&c4, &m4);
            printf("Final   : x1 = %d, x2 = %d\n", x1, x2);
        }
        printf("Result   : x1 = %d, x2 = %d\n", x1, x2);
        pthread_mutex_unlock(&m3);
        pthread_mutex_unlock(&m4);
        pthread_cancel(pth1);
        pthread_cancel(pth2);
        return 1;
    }

Proposed Solution Using Semaphore: Initialize 4 semaphore and invoke separate threads for separate increment of variable. 2 semaphores for passing message to threads for start incrementing and 2 semaphores for passing message to main thread that incrementation is completed. Main thread will wait for semaphore posting from both child threads showing incrementation of both variable is done, then main thread will pass message to both child threads allowing further incrementing.

Semaphore Code:

    #include <stdio.h>
    #include <pthread.h>
    #include <semaphore.h>

    //Threads
    pthread_t pth1,pth2;

    //Values to calculate
    int x1 = 0, x2 = 0;

    sem_t c1,c2,c3,c4;

    void *threadfunc1(void *parm)
    {
        for (;;) {
            x1++;
            sem_post(&c1);
            sem_wait(&c3);
        }
        return NULL ;
    }

    void *threadfunc2(void *parm)
    {
        for (;;) {
            x2++;
            sem_post(&c2);
            sem_wait(&c4);
        }
        return NULL ;
    }

    int main () {
        sem_init(&c1, 0, 0);
        sem_init(&c2, 0, 0);
        sem_init(&c3, 0, 0);
        sem_init(&c4, 0, 0);
        pthread_create(&pth1, NULL, threadfunc1, "foo");
        pthread_create(&pth2, NULL, threadfunc2, "foo");
        sem_wait(&c1);
        sem_wait(&c2);
        sem_post(&c3);
        sem_post(&c4);
        int loop = 0;
        while (loop < 8) {
            // iterated as a step
            loop++;
            printf("Initial   : x1 = %d, x2 = %d\n", x1, x2);
            sem_wait(&c1);
            sem_wait(&c2);
            printf("Final   : x1 = %d, x2 = %d\n", x1, x2);
            sem_post(&c3);
            sem_post(&c4);
        }
        sem_wait(&c1);
        sem_wait(&c2);
        sem_destroy(&c1);
        sem_destroy(&c2);
        sem_destroy(&c3);
        sem_destroy(&c4);
        printf("Result   : x1 = %d, x2 = %d\n", x1, x2);
        pthread_cancel(pth1);
        pthread_cancel(pth2);
        return 1;
    }

Please suggest me, which one is better way to implement or where can i improve? Any kind of suggestions will be helpful. Thanks in advance. And sorry, if i am repeating myself, because, this problem has become a nightmare for me.. Please help.

Vishwadeep Singh
  • 1,043
  • 1
  • 13
  • 38
  • Have you tried benchmarking each results? For your need does it meet the benchmark criteria? Can you post the results? – kumar_m_kiran Sep 04 '13 at 09:00
  • I tried it, for me semaphore is faster.. But, is there any better way to make it more faster.. It seems, posting and receiving message from threads is a costly way... @kumar_m_kiran – Vishwadeep Singh Sep 04 '13 at 09:05
  • It's relatively costly if a message is controlling the increment of one integer. If the message is signaling the thread to perform complex processing of a 10MB image buffer, the inter-thread comms overhead is negligible. – Martin James Sep 04 '13 at 10:17
  • Have you tried benchmarking this without the threading? It seems to me that the overhead of the semaphores/mutexes is going to be bigger than the work being done. – Dan Puzey Dec 16 '13 at 11:14
  • No @DanPuzey that was just a sample of code. There is a very big slot of calculation. Suppose it take 400sec to complete the calculation on single thread for 1 million calculations. But if i am dividing calculations equally on two threads then time is increasing 550sec and then for 3 threads 570sec and for 4 it reached 600sec and so on it keep on increasing. But tested on i5 this time is reducing from 400sec -> 340sec -> 290sec and 250sec and so on.. – Vishwadeep Singh Dec 16 '13 at 11:20

0 Answers0