Multithreading – how to reliably pass a signal to another thread in a pthread?

I tried to write a simple thread pool program in pthread However, it seems that pthread_ cond_ Signal will not block, which will cause problems For example, suppose I have a "producer consumer" program:

pthread_cond_t my_cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t my_cond_m = PTHREAD_MUTEX_INITIALIZER;

void * liberator(void * arg)
{
    // XXX make sure he is ready to be freed
    sleep(1);

    pthread_mutex_lock(&my_cond_m);
    pthread_cond_signal(&my_cond);
    pthread_mutex_unlock(&my_cond_m);

    return NULL;
}

int main()
{
    pthread_t t1;
    pthread_create(&t1,NULL,liberator,NULL);

    // XXX Don't take too long to get ready. Otherwise I'll miss 
    // the wake up call forever
    //sleep(3);

    pthread_mutex_lock(&my_cond_m);
    pthread_cond_wait(&my_cond,&my_cond_m);
    pthread_mutex_unlock(&my_cond_m);

    pthread_join(t1,NULL);

    return 0;
}

As described in the two XXX tags, if I take away the sleep call, main() may fail because the wake-up call has been ignored from the libraror() Of course, sleep is not a very powerful way to ensure

In real life, this will be a worker thread that tells the administrator thread that it is ready to work, or the administrator thread announces that new work is available

How do you reliably perform this operation in pthread?

essence

@Borealid's answer works, but his explanation of this question may be better I suggest anyone look at this question to read the discussion in the comments to understand what happened

In particular, I will modify his answers and code examples to make them clearer (since borealid's original answer, compilation and work, I have been confused a lot)

// In main
pthread_mutex_lock(&my_cond_m);

// If the flag is not set,it means liberator has not 
// been run yet. I'll wait for him through pthread's signaling 
// mechanism

// If it _is_ set,it means liberator has been run. I'll simply 
// skip waiting since I've already synchronized. I don't need to 
// use pthread's signaling mechanism
if(!flag) pthread_cond_wait(&my_cond,&my_cond_m);

pthread_mutex_unlock(&my_cond_m);

// In liberator thread
pthread_mutex_lock(&my_cond_m);

// Signal anyone who's sleeping. If no one is sleeping yet,// they should check this flag which indicates I have already 
// sent the signal. This is needed because pthread's signals 
// is not like a message queue -- a sent signal is lost if 
// nobody's waiting for a condition when it's sent.
// You can think of this flag as a "persistent" signal
flag = 1;
pthread_cond_signal(&my_cond);
pthread_mutex_unlock(&my_cond_m);

Solution

Use synchronous variables

Main contents:

pthread_mutex_lock(&my_cond_m);
while (!flag) {
    pthread_cond_wait(&my_cond,&my_cond_m);
}
pthread_mutex_unlock(&my_cond_m);

In the thread:

pthread_mutex_lock(&my_cond_m);
flag = 1;
pthread_cond_broadcast(&my_cond);
pthread_mutex_unlock(&my_cond_m);

For the producer - consumer problem, this will be that the consumer sleeps when the buffer is empty and the producer sleeps when it is full Remember to acquire locks before accessing global variables

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>