Synchronisation before pthread_cond_broadcast

2019-09-11 15:33发布

问题:

I want to send a broadcast signal from the main thread to all the other threads waiting for a condition. It seems to me that the broadcast signal comes to early to the threads.

#include <iostream>
#include <pthread.h>

#define NUM 4
#define SIZE 256

using namespace std;

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_barrier_t barrier;

class cache{
    int lv1;
public:
    int write(int i){
        lv1=i;
        pthread_cond_broadcast(&cond);
    }
};

cache c[NUM];

void *thread(void *arg){
   int i = (int)arg;
   for(;;){
       pthread_mutex_lock(&mutex);
       pthread_cond_wait(&cond,&mutex);
       cout << "Thread: "<< i << endl;
       //do some work
       pthread_mutex_unlock(&mutex);
   }
}


int main()
{
    pthread_t tid[NUM];
    pthread_barrier_init(&barrier,NULL,NUM+1);

    for(int i=0;i<NUM;i++){
        pthread_create(&tid[i],NULL,thread,(void*)i);
    }

    //Sleep(2);
    c[0].write(55);  //broadcast signal
    //Sleep(2);
    c[1].write(44);  //broadcast signal

    for(int i=0;i<NUM;i++){
        pthread_join(tid[i],NULL);
    }

    cout << "Hello world!" << endl;
    return 0;
}

If I insert Sleep(2) in the main function, it works, but I do not want to wait a time but a synchronisation before calling pthread_broadcast. I thought of a barrier, but pthread_cond_wait is blocking, right?

回答1:

You need to read up on how condition variables are used. You also handled the integer arguments to your threads erroneously. Here is a fixed version, hopefully similar to what you wanted:

#include <iostream>
#include <pthread.h>
#include <unistd.h>

#define NUM 4
#define SIZE 256

using namespace std;

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_barrier_t barrier;

class cache{
    int lv1;
public:
    int write(int i) { lv1=i; }
    const int val() { return lv1; }
};

cache c[NUM];

void *thread(void *arg)
{
    int i = *(int*)arg;
    for(;;) {
        pthread_mutex_lock(&mutex);
        // Check predicate, do not go to sleep if predicate is fulfilled                                                                                                                                                                                                                                                                                                                    
        if (c[0].val() > 0 && c[1].val() > 0) {
            cout << "Thread " << i << " leaving...\n";
            pthread_mutex_unlock(&mutex);
            return 0;
        }
        pthread_cond_wait(&cond, &mutex);
        cout << "Thread wakeup: "<< i << endl;
        // do some work                                                                                                                                                                                                                                                                                                                                                                     
        pthread_mutex_unlock(&mutex);
    }
}


int main()
{
    pthread_t tid[NUM];

    int arg[NUM];
    for(int i=0; i<NUM; i++) {
        arg[i] = i; // make a copy of i used by only one thread                                                                                                                                                                                                                                                                                                                             
        pthread_create(&tid[i], NULL, thread,(void*)&arg[i]);
    }

    pthread_mutex_lock(&mutex);
    c[0].write(55);
    c[1].write(44);
    pthread_mutex_unlock(&mutex);
    pthread_cond_broadcast(&cond); // Signal all threads that predicate is fulfilled                                                                                                                                                                                                                                                                                                        


    for(int i=0; i<NUM; i++) {
        pthread_join(tid[i],NULL);
        cout << "Joined " << i << '\n';
    }

    cout << "Hello world!" << endl;
    return 0;
}


回答2:

Sequence how I think it is

This is how it is right now I think, I still need a way to synchronise, before I send the broadcast signal.

In that picture, the first pthread_broadcast comes too early.