0

RESOLVED I am having some problems with synchronization.

Firstly, the purpose of the file is to create 10 threads, and print the odd numbered ids before the even numbered ids.

As far as I can tell, my pthread_cond_wait is creating a deadlock. I was able to resolve this deadlock by including the signal below in the threadFunction. If I do not include this, I am stuck in running the program after all the odd numbers thread ids have been printed.

        perror("Unable to pthread_cond_broadcast");
        exit(EXIT_FAILURE);
      }

Updated Section - Solution

void *threadFunction(void *threadId) {
    if ((long) threadId % 2 == 0 && remainingOddThreads > 0) {
        pthread_mutex_lock(&lock);
        if (pthread_cond_wait(&evenCanGo, &lock)) {
            perror("Error setting a pthread_cond_wait:");
            exit(EXIT_FAILURE);
        }
        printf("Hello from thread[%ld]!\n", (long) threadId);
        pthread_mutex_unlock(&lock);
    } else {
        if (pthread_mutex_lock(&lock)) {
            perror("Unable to lock mutex:");
            exit(EXIT_FAILURE);
        }
        printf("Hello from thread[%ld]!\n", (long) threadId);
        remainingOddThreads--;
        if (pthread_mutex_unlock(&lock)) {
            perror("Unable to unlock mutex:");
            exit(EXIT_FAILURE);
        }
    }
    if (remainingOddThreads == 0) {
        pthread_mutex_lock(&lock);
        if (pthread_cond_signal(&evenCanGo)) {
            perror("Unable to pthread_cond_broadcast");
            exit(EXIT_FAILURE);
        }
        pthread_mutex_unlock(&lock);
    }
    return NULL;
}

This is the OLD code file

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

#define NUMBER_OF_ODD_NUMBERS_FROM_ONE_TO_TEN 5;
#define NUMBER_OF_THREADS 10
int remainingOddThreads = NUMBER_OF_ODD_NUMBERS_FROM_ONE_TO_TEN
pthread_t threads[NUMBER_OF_THREADS];
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t evenCanGo = PTHREAD_COND_INITIALIZER;

void *threadFunction(void *threadId) {
    if ((long) threadId % 2 == 0 && remainingOddThreads > 0) {
        if (pthread_cond_wait(&evenCanGo, &lock)) {
            perror("Error setting a pthread_cond_wait:");
            exit(EXIT_FAILURE);
        }
        printf("Hello from thread[%ld]!\n", (long) threadId);
    } else {
        if (pthread_mutex_lock(&lock)) {
            perror("Unable to lock mutex:");
            exit(EXIT_FAILURE);
        }
        printf("Hello from thread[%ld]!\n", (long) threadId);
        remainingOddThreads--;
        if (pthread_mutex_unlock(&lock)) {
            perror("Unable to unlock mutex:");
            exit(EXIT_FAILURE);
        }
    }
    if (pthread_cond_signal(&evenCanGo)) {
        perror("Unable to pthread_cond_broadcast");
        exit(EXIT_FAILURE);
    }
    return NULL;
}


void createThreads() {
    for (long i = 1; i <= NUMBER_OF_THREADS; i++) {
        int status = pthread_create(&threads[i - 1], NULL, threadFunction, (void *) i);
        if (status) {
            perror("Failed to create thread");
            exit(EXIT_FAILURE);
        }
    }
}

void activateThreads() {
    for (long i = 0; i < NUMBER_OF_THREADS; i++) {
        int status = pthread_join(threads[i], NULL);
        if (status > 0) {
            perror("Unable to join thread");
            exit(EXIT_FAILURE);
        }
    }
}


int main() {
    createThreads();
    activateThreads();

    if (pthread_cond_destroy(&evenCanGo) != 0) {
        perror("Unable to destroy pthread_cond_t object:");
        exit(EXIT_FAILURE);
    }
    pthread_mutex_unlock(&lock);
    if (pthread_mutex_destroy(&lock) != 0) {
        perror("Unable to destroy pthread_mutex_t object:");
        printf("%d", errno);
        exit(EXIT_FAILURE);
    }
    return 0;
}
  • 1
    Do you write C or C++? – 12431234123412341234123 Oct 01 '20 at 10:25
  • 1
    You're supposed to have locked the lock when you call pthread_cond_wait. And you're supposed to check the thing you're waiting for, after locking the lock, before calling pthread_cond_wait. – user253751 Oct 01 '20 at 10:35
  • The locking is completely wrong. `remainingOddThreads` can only be modified while holding a lock. The shown code does not. `pthread_cond_signal` can only be called while holding a lock. The shown code does not. Finally, there's nothing that prevents all odd threads from signaling the condition variable, all at once, before any of the even threads attempt to wait for the condition variable's signal. The logic is fundamentally flawed. – Sam Varshavchik Oct 01 '20 at 11:07
  • @user253751 Thank you both. I was able to figure out why things were not going well after your explanation. I'm going to spend some more time reading the manual (since it's pretty confusing). I've updated the sample code with the solution. – ImposterSyndrome2 Oct 01 '20 at 17:35
  • @SamVarshavchik Thank you both. I was able to figure out why things were not going well after your explanation. I'm going to spend some more time reading the manual (since it's pretty confusing). I've updated the sample code with the solution. – ImposterSyndrome2 Oct 01 '20 at 17:35

0 Answers0