0

I created 44 threads with only 6 threads running in the same time and I want thread 13 to end only when the value of the semaphore is 0 (another 5 threads are running). I tried with a condition variable something like this:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <fcntl.h>
int curr_threads = 0;
int sem_id;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t end13 = PTHREAD_COND_INITIALIZER;

void P(int sem_id){
    struct sembuf semaphore_op = {0, -1, 0};
    semop(sem_id, &semaphore_op, 1);    
}

void V(int sem_id){
    struct sembuf semaphore_op = {0, 1, 0};
    semop(sem_id, &semaphore_op, 1);    
}

void* thread_func(void* arg) {
    P(sem_id);
    pthread_mutex_lock(&mutex);
    curr_threads++;
    if(curr_threads == 6) pthread_cond_signal(&end13);
    pthread_mutex_unlock(&mutex);
    int* thread_nr = (int*) arg;
    if(*thread_nr == 13) {
        pthread_mutex_lock(&mutex);
        pthread_cond_wait(&end13, &mutex);
        pthread_mutex_unlock(&mutex); 
    }
    pthread_mutex_lock(&mutex);
    curr_threads--;
    pthread_mutex_unlock(&mutex);
    V(sem_id);
    return (void*) 0;
}
int main(int argc, char** argv) {
    sem_id = semget(1234, 1, IPC_CREAT | 0600);
    pthread_t threads[44];
    semctl(sem_id, 0, SETVAL, 6);
    int aux[44];
    for(int i = 0; i < 44; i++) {
        aux[i] = i + 1;
    }

    for(int i = 0; i < 44; i++) {
        pthread_create(&threads[i], NULL, thread_func, &aux[i]);
    }

    for(int i = 0; i < 44; i++) {
        pthread_join(threads[i], NULL);
    }        
    exit(0);
}

But it doesn`t work. Any suggestions?

  • 1
    Many threads waiting and only a few active, that sounds like you want a *thread pool* with *work queues*. Then you could dispatch work to waiting threads in the order and amount you want. You might want to do some research about those terms. – Some programmer dude May 04 '20 at 18:52

1 Answers1

0
if(*thread_nr == 13) {
    pthread_mutex_lock(&mutex);
    pthread_cond_wait(&end13, &mutex);
    pthread_mutex_unlock(&mutex); 
}

Condition variables are stateless and require you to use their associated mutex to protect the state. The mutex doesn't protect anything here, so you aren't waiting for anything. You will never get a condition variable to work correctly this way.

Your code is most likely failing because this thread is calling pthread_cond_wait even when there is nothing to wait for, and so it waits forever. You acquired the mutex to check the shared state, but then you didn't do that.

You need to either not use condition variables or learn how they work. In particular, you must understand that fundamentally they provide an atomic "unlock and wait" operation to avoid a race condition where you wait for something that has already happened.

Reading this question and its answers may help.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278