让我们先看看这个手残的程序……
这是一个简单的生产者消费者问题。
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/syscall.h>int buffer;
int count = 0;
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t empty = PTHREAD_COND_INITIALIZER;
pthread_cond_t fill = PTHREAD_COND_INITIALIZER;void put(int value){assert(count == 0);buffer = value;count = 1;
}int get(){assert(count == 1);count = 0;return buffer;
}// gettid
pid_t get_thr_tid(){pid_t tid = syscall(__NR_gettid);return tid;
}void* producer(void *arg){printf("producer(tid: %d) running\n", get_thr_tid());int loops = *(int *)arg; // gross productfor(int i = 0; i < loops; i++){pthread_mutex_lock(&lock);while(count == 1){ // if the buffer is full,stop producing!pthread_cond_wait(&empty, &lock);}put(i);printf("produce(tid: %d): %d\n", get_thr_tid(), buffer);pthread_cond_signal(&fill); // Wake up the sleepy consumers.pthread_mutex_unlock(&lock);}return NULL;
}void* consumer(void *arg){printf(" consumer(tid: %d) running\n", get_thr_tid());int loops = *(int *)arg; // max consume countsfor(int i = 0; i < loops; i++){pthread_mutex_lock(&lock);while(count == 0){ // if the buffer is empty,stop consuming!pthread_cond_wait(&fill, &lock);}int tmp = get(i);printf(" consume(tid: %d): %d\n", get_thr_tid(), tmp);pthread_cond_signal(&empty); // Wake up the sleepy producers.pthread_mutex_unlock(&lock);}return NULL;
}int main(int argc, char *argv[]){if(argc != 4){fprintf(stderr,"please input options: <loops> <producer_count> <consumer_count>\n");exit(1);}int loops = atoi(argv[1]);int producer_count = atoi(argv[2]);int consumer_count = atoi(argv[3]);printf("main thread running!\n");// create some threadspthread_t p[producer_count];pthread_t c[consumer_count];for(int i = 0; i < producer_count; i++){pthread_create(&p[producer_count], NULL, producer, (void *)&loops);}for(int i = 0; i < consumer_count; i++){pthread_create(&c[consumer_count], NULL, consumer, (void *)&loops);}for(int i = 0; i < producer_count; i++){pthread_join(p[producer_count], NULL);}for(int i = 0; i < consumer_count; i++){pthread_join(c[consumer_count], NULL);}printf("main thread done!\n");return 0;
}
这里最大的问题在后面创建和等待线程的时候
for(int i = 0; i < producer_count; i++){pthread_create(&p[producer_count], NULL, producer, (void *)&loops);}for(int i = 0; i < consumer_count; i++){pthread_create(&c[consumer_count], NULL, consumer, (void *)&loops);}for(int i = 0; i < producer_count; i++){pthread_join(p[producer_count], NULL);}for(int i = 0; i < consumer_count; i++){pthread_join(c[consumer_count], NULL);}
本来很多地方应该使用i
的!实际应该是这样:
for(int i = 0; i < producer_count; i++){pthread_create(&p[i], NULL, producer, (void *)&loops);}for(int i = 0; i < consumer_count; i++){pthread_create(&c[i], NULL, consumer, (void *)&loops);}for(int i = 0; i < producer_count; i++){pthread_join(p[i], NULL);}for(int i = 0; i < consumer_count; i++){pthread_join(c[i], NULL);}
出于某种原因,楼主将后面的改正确了,前面不知道有问题,这就导致了下面的思考:
创建了线程pthread_t c[5]
的数组,然后使用pthread_join()
的时候,不是出现Segmentation fault
就是出现pthread join error 3
目前还不知道咋回事……
不知道为啥,使用数组就不行,单独创建多个变量就没事……
先在主线程使用pthread_exit(0)
而不是return 0
暂时避开问题了。
后来找了很多资料也没有解决,直到发现……线程创建一直在使用同一个pthread_t
变量,并且使用同一个变量,创建了多个线程,而后面在没改之前,也是使用循环,等待了同一个变量多次……错错得对,这个程序居然可以正常运行!
不清楚什么情况……后续再研究对于同一个pthread_t
变量创建多个线程且等待多次的情况吧,就很神奇……
总结: 如果太手残,找bug会很心碎,因为你不知道你哪里手残了,且不是语法错误,而是逻辑错误,报错点也不是你手残的点。
!!
这里需要注意,对于pthread_join的报错,得联合看看,线程创建好了没有!是不是joinable的!