C - How to terminate all threads after one of them signals the main thread with a condition variable?

Viewed 330

In my program the main thread starts multiple child threads, locks a mutex for a counter and then sleeps until the counter reaches N.

In an infinite for loop, the other threads do some work and they increase the counter in each iteration alternately. Once the counter == N one of them has to signal the main thread and all of the child threads have to end.

My problem is that I'm not sure when I should lock the counter mutex and make a signal in the thread function, because once the counter becomes N I managed to wake up the main thread and exit one of the child threads, but the other threads will keep on trying to work when they should all be terminating.

My question is, how can I check if counter == N but send a signal by only one of the threads, and the others just return without any signalling? Can this be done by only locking the mutex once in each iteration, for the time of checking its value (== N)? If yes, how?

void *thread_function(void *arg) {
    int *id = (int *) arg;

    for (;;) {
        pthread_mutex_lock(&mutex_counter);
        counter++;
        if (counter == N) {
            pthread_cond_signal(&cond);
            pthread_mutex_unlock(&mutex_counter);
            return NULL;
        }
        if (counter > N) {
            pthread_mutex_unlock(&mutex_counter);
            return NULL;
        }
        pthread_mutex_unlock(&mutex_counter);
        
        sleep(random());
        // do some work here
        // ...
        // finish work
    }

The problem with above code is that, despite all threads terminating, they execute the loop one less iteration than needed because the counter is increased before the if clause (so counter will be N, but there were no N loops of work done).

However, if I put the counter to the end of the function, the threads will do more work than needed which messes up my program.

1 Answers

why you lock counter-mutex in main thread? Why you need to send signal from other treads to main? If you have only one global counter and all threads increasing it, you can just start in main thread all threads, remember their thread ids and then wait using while(counter<N); instruction. After all, just kill all threads with pthread_cancel.

Related