我写了一个像这样的多线程程序,
#include <queue>
#include <cstdio>
#include <cstdlib>
#include <pthread.h>
#include <unistd.h>
using namespace std;
pthread_mutex_t mu = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t ec = PTHREAD_COND_INITIALIZER;
pthread_cond_t fc = PTHREAD_COND_INITIALIZER;
queue<int> qu;
const int N = 2;
void *producer(void *arg)
{
while(1) {
pthread_mutex_lock(&mu);
int tmp = rand();
qu.push(tmp);
pthread_cond_signal(&ec);
if ((int) qu.size() > N) {
pthread_cond_wait(&fc, &mu);
}
pthread_mutex_unlock(&mu);
}
}
void *consumer(void *arg)
{
while(1) {
pthread_mutex_lock(&mu);
if ((int) qu.size() < 1) {
pthread_cond_wait(&ec, &mu);
}
int tmp = qu.front();
qu.pop();
if ((int) qu.size() <= N) {
pthread_cond_signal(&fc);
}
pthread_mutex_unlock(&mu);
//sleep(1);
}
}
int main()
{
pthread_t tid;
pthread_create(&tid, NULL, producer, NULL);
for (int i = 0; i < N; i++) {
pthread_t tid;
pthread_create(&tid, NULL, consumer, NULL);
}
printf("all created\n");
sleep(600);
}
如果qu.size()
比N
更好,producer
应该停止生成,当它小于N
时,producer
会恢复生成。
我们遇到的问题是,如果我删除了sleep(1);
中的consumer
,程序会遇到segmentation fault
,如果我保留sleep(1);
,程序就会运行正常。< / p>
为什么呢?这是否意味着consumer
消耗得太快了?
答案 0 :(得分:4)
Spurious wakeup可能是原因。如果条件为真,你的线程将继续,但如果你的线程继续,你不能认为条件是真的。
可能会发生pthread_cond_timedwait()或pthread_cond_wait()函数的虚假唤醒。由于从pthread_cond_timedwait()或pthread_cond_wait()返回并不意味着有关此谓词的值的任何内容,因此应在返回时重新评估谓词。
所以例如
if (qu.size() == 0) {
pthread_cond_wait(&ec, &mu);
}
应该成为
while (qu.size() == 0) {
pthread_cond_wait(&ec, &mu);
}
答案 1 :(得分:1)
如果你保持sleep(1)
电话,整个事情都不会崩溃,那你就是幸运的。)
尝试使用pthread_mutex_init()显式初始化互斥锁,否则你的pthread_mutex_lock()调用似乎失败。
来自the docs:
Errors
The pthread_mutex_lock() and pthread_mutex_trylock()
functions may fail if:
EINVAL: The value specified by mutex
does not refer to an initialized mutex object.