pthread_cond_wait和pthread_mutex_lock无法按预期工作

时间:2016-04-20 14:49:23

标签: c++ multithreading pthreads threadpool

我创建了一个ThreadPool类,并在execute_thread_helper()内调用了一个名为void* execute_thread(void* arg)的void函数(这是一个以这种方式赋予线程的函数:ret = pthread_create(&workers[i], NULL, execute_thread, (void*)this);

void ThreadPool::execute_thread_helper()
{
    Task task;

    pthread_mutex_lock(&mutex);

    while(TaskList.empty()) // Previously "if"
    {
        cout << "Thread #"  << pthread_self() << " is blocked. "<< endl;
        pthread_cond_wait(&conditionVar, &mutex);
    }

    task = TaskList.front();
    TaskList.pop();

    cout << "Thread #"  << pthread_self() << " going to run the function. "<< endl;

    threadFunction(task);

    pthread_mutex_unlock(&mutex);
}

任务以这种方式添加到任务队列 -

void ThreadPool::add_task(Task newTask)
{    
    pthread_mutex_lock(&mutex);

    TaskList.push(newTask);    
    pthread_cond_signal(&conditionVar); 

    pthread_mutex_unlock(&mutex);

}

据我所知,一旦创建了一个线程,它就会尝试运行execute_thread。然后,给定一个空的队列,我希望pthread_cond_wait&#34; put&#34;要睡眠的线程(并对所有创建的线程执行),直到它被pthread_cond_signal中的add_task唤醒。

嗯..我尝试在单个线程上检查程序,并得到了这个结果(我没有add_task。只是试图创建池) -

Thread #139859560904448 is blocked. 
Thread #139859560904448 going to run the function. 
in map() key is   and value is 0 

我不明白线程是如何传递if语句的,如果它先前被搁置了。

尝试创建3个线程池时输出

-

Thread #140013458028288 is blocked. 
Thread #140013458028288 going to run the function. 
in map() key is   and value is 0 
Thread #140013458028288 going to run the function. 
in map() key is   and value is 0 
Thread #140013458028288 going to run the function. 
in map() key is   and value is 0 

为什么其他两个主题没有被搁置?

修改

感谢SergeyA,同时切换if,确实有所帮助。 但是,仍然试图制作3个线程池,结果就是这个 -

Thread #139916558706432 is blocked. 
Thread #139916558706432 is blocked. 
Thread #139916558706432 is blocked. 
Thread #139916558706432 is blocked. 
Thread #139916558706432 is blocked. 
Thread #139916558706432 is blocked. 
Thread #139916558706432 is blocked. 
Thread #139916558706432 is blocked. 

为什么没有创建其他线程?他们都应该被创建,同时运行并交替打印它们被阻止了吗?

2 个答案:

答案 0 :(得分:2)

条件变量容易出现所谓的* spurios唤醒。这意味着代码被解锁,但条件并没有真正改变,也没有发出信号。

这就是为什么你总是要在循环中调用wait函数,并在每次唤醒后检查条件。

答案 1 :(得分:0)

pthread_cond_signal(&conditionVar);只会唤醒等待线程的一个。如果您的任务足够短,您将偶然唤醒同一个线程。没有公平。 : - )

您还可以使用pthread_cond_broadcast(&conditionVar);唤醒所有等待的线程。然后你应该看到所有的线程总是被唤醒。但是对于你的线程池,不需要使用广播变体。