【操作系统】使用循环创建线程,一个手残导致的bug
程序员文章站
2022-06-19 10:59:25
...
让我们先看看这个手残的程序……
这是一个简单的生产者消费者问题。
#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 product
for(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 counts
for(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 threads
pthread_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的!
上一篇: Linux多线程应用程序--新手练习程序
下一篇: H5 _拖放使用