pthread_cond_wait从pthread_cond_signal丢失信号

时间:2014-04-08 14:20:36

标签: c++ c multithreading linux-kernel

我创建了多个线程,并希望使用条件变量以循环方式运行它们 和信号(pthread_cond_wait& pthread_cond_signal)。

我使用了两种方法,一种方法正在工作但浪费CPU而其他方法无效, 不要浪费CPU。

我面临的问题是之前发送的信号 我的线程等待,信号丢失。所以它会进入无限的等待循环。

第一种方法:

创建线程并等待条件变量并持续检查被调用的变量 作为状态(在while循环中)。

当state == my_id时,带有my_id的线程被激活,然后它发信号到下一个线程my_id + 1等等 上。

DRAWBACK:CPU的浪费

第二种方法:

创建线程并等待其自身条件变量的信号。现在信号已经存在 在线程开始等待之前发送,信号丢失,程序进入无限等待循环。

是否有类似" Self Signaling"或者在信号丢失时发送信号的其他方式?

我在linux下使用g ++。任何线索都将受到高度赞赏。提前谢谢。

第一种方法的计划在round robin

这是我的第二种方法:

#include <pthread.h>
#include <stdio.h>
#include <iostream>
#include <mutex>          // std::mutex


#define MULTIPLE_THREADS 2
#define NTHREADS MULTIPLE_THREADS*64
#define NO_OF_LOOP 1


pthread_cond_t      cond[NTHREADS];
pthread_mutex_t     mutex1 = PTHREAD_MUTEX_INITIALIZER;


using namespace std;



/* This is our thread function.  It is like main(), but for a thread*/
void *threadA(void *arg)
{ 
    long my_id = (long)arg;
    int i = 0;

    while(i < NO_OF_LOOP)
    {


        // Awaken or unblocked by thread (i-1) 
        pthread_mutex_lock(&mutex1);
        pthread_cond_wait(&cond[my_id], &mutex1);
        pthread_mutex_unlock(&mutex1);

        printf("I am thread - %ld",my_id);
        ++i;


         /* wake up thread i+1 */
        pthread_mutex_lock(&mutex1);
        pthread_cond_signal(&cond[(my_id + 1) % NTHREADS]);
        pthread_mutex_unlock(&mutex1);      
    }

    return NULL;
}

int main(void)
{

    pthread_t             threadid[NTHREADS];


    // Initialization   
    for(int i=0;i<NTHREADS;i++)
    cond[i]= PTHREAD_COND_INITIALIZER;

    //printf("Create %d threads\n", NTHREADS);
    for(long i=0; i<NTHREADS; ++i) {
    pthread_create(&threadid[i], NULL, threadA, (void *)i);
    //printf("Thread created=%d\n", i);
    }

    //  printf("Wait for threads and cleanup\n");
    for (long i=0; i<NTHREADS; ++i) {
    pthread_join(threadid[i], NULL);
    }

    return 0;
}

1 个答案:

答案 0 :(得分:2)

您不能以这种方式使用条件变量。你总是需要一个谓词。也就是说,你需要 一个变量,您可以测试事件是否已发生。

简单地发出盲目的pthread_cond_wait和pthread_cond_signal会让你输掉比赛。 可能有spurious wakeups,如果您发信号的线程未在pthread_cond_wait()中被阻止,它将错过该事件(pthread_cond_signal()不排队)。

你需要这样的东西(未经测试):

pthread_cond_t      cond[NTHREADS];
int                 wakeup[NTHREADS];
pthread_mutex_t     mutex1 = PTHREAD_MUTEX_INITIALIZER;


using namespace std;



/* This is our thread function.  It is like main(), but for a thread*/
void *threadA(void *arg)
{ 
    long my_id = (long)arg;
    int i = 0;

    while(i < NO_OF_LOOP)
    {


        // Awaken or unblocked by thread (i-1) 
        pthread_mutex_lock(&mutex1);
        while (!wakeup[my_id]) {
            pthread_cond_wait(&cond[my_id], &mutex1);
        }
        wakeup[my_id] = 0;
        pthread_mutex_unlock(&mutex1);

        printf("I am thread - %ld",my_id);
        ++i;

        pthread_mutex_lock(&mutex1);
        //tell thread i to wake up
        wakeup[(my_id + 1) % NTHREADS] = 1; 
        pthread_cond_signal(&cond[(my_id + 1) % NTHREADS]);
        pthread_mutex_unlock(&mutex1);      
    }

    return NULL;
}
int main(void)
{

    pthread_t             threadid[NTHREADS];
    wakeup[0] = 1; //let thread 0 start.

EDIT。 #define NTHREADS MULTIPLE_THREADS*64宏也出现了另一个错误。 表达式(my_id + 1) % NTHREADS将无法正确计算,宏必须为

 #define NTHREADS (MULTIPLE_THREADS*64)

由于stdout通常是行缓冲的,因此在printf中添加换行符,以便立即看到输出。

 printf("I am thread - %ld\n",my_id);