2009-12-16 102 views
0

我写了一个简单的多线程C程序来访问MySQL,它工作正常,除了,当我在每个线程函数中添加usleep()或sleep()函数。 我创建在主方法二并行线程,多线程访问MySQL错误

int main(){ 
     mysql_library_init(0,NULL,NULL); 
     printf("Hello world!\n"); 
     init_pool(&p,100); 
     pthread_t producer; 
     pthread_t consumer_1; 
     pthread_t consumer_2; 
     pthread_create(&producer,NULL,produce_fun,NULL); 
     pthread_create(&consumer_1,NULL,consume_fun,NULL); 
     pthread_create(&consumer_2,NULL,consume_fun,NULL); 
     mysql_library_end(); 
} 



    void * produce_fun(void *arg){ 
    pthread_detach(pthread_self()); 
    //procedure 
    while(1){ 
     usleep(500000); 
     printf("producer...\n"); 
     produce(&p,cnt++); 
    } 
    pthread_exit(NULL); 
} 

void * consume_fun(void *arg){ 
    pthread_detach(pthread_self()); 
    MYSQL db; 
    MYSQL *ptr_db=mysql_init(&db); 
    mysql_real_connect(); 

    //procedure 
    while(1){ 
     usleep(1000000); 
     printf("consumer..."); 
     int item=consume(&p); 
     addRecord_d(ptr_db,"test",item); 
    } 
    mysql_thread_end(); 
    pthread_exit(NULL); 
} 

void addRecord_d(MYSQL *ptr_db,const char *t_name,int item){ 
    char query_buffer[100]; 
    sprintf(query_buffer,"insert into %s values(0,%d)",t_name,item); 
//pthread_mutex_lock(&db_t_lock); 
    int ret=mysql_query(ptr_db,query_buffer); 
    if(ret){ 
     fprintf(stderr,"%s%s\n","cannot add record to ",t_name); 
     return; 
    } 

    unsigned long long update_id=mysql_insert_id(ptr_db); 
// pthread_mutex_unlock(&db_t_lock); 
    printf("add record (%llu,%d) ok.",update_id,item); 
} 

像节目输出错误:

[Thread debugging using libthread_db enabled] 
[New Thread 0xb7ae3b70 (LWP 7712)] 
Hello world! 
[New Thread 0xb72d6b70 (LWP 7713)] 
[New Thread 0xb6ad5b70 (LWP 7714)] 
[New Thread 0xb62d4b70 (LWP 7715)] 
[Thread 0xb7ae3b70 (LWP 7712) exited] 
producer... 
producer... 
consumer...consumer...add record (31441,0) ok.add record (31442,1) ok.producer... 
producer... 
consumer...consumer...add record (31443,2) ok.add record (31444,3) ok.producer... 
producer... 
consumer...consumer...add record (31445,4) ok.add record (31446,5) ok.producer... 
producer... 
consumer...consumer...add record (31447,6) ok.add record (31448,7) ok.producer... 
Error in my_thread_global_end(): 2 threads didn't exit 
[Thread 0xb72d6b70 (LWP 7713) exited] 
[Thread 0xb6ad5b70 (LWP 7714) exited] 
[Thread 0xb62d4b70 (LWP 7715) exited] 

Program exited normally. 

,当我在功能addRecord_d的pthread_mutex_lock添加,错误依然存在。 那究竟是什么问题呢?

回答

0

当你的生产者和消费者线程睡觉,他们握住MySQL连接这是开放的各个功能的持续时间。

当程序试图结束,机会是那些线程正在睡觉,并且不能接收终止信号。因此从my_thread_global_end()错误。

我没有获得一个开发环境,现在,所以我不能尝试你的样品。但我认为,这可能让过去的错误,但是这将是一个非常低效的代码(从consume_fun功能样品):

//procedure 
while(1){ 
    usleep(1000000); 

    MYSQL *ptr_db=mysql_init(&db); 
    mysql_real_connect(); 

    printf("consumer..."); 
    int item=consume(&p); 
    addRecord_d(ptr_db,"test",item); 

    mysql_thread_end(); 
} 

简而言之,上述样品应该强制连接建立和外关闭睡眠周期。我不认为这是最好的代码,但出于说明的目的,这应该排除错误。

请记住:这将迫使你打开,并在一个循环,这将是一个“生产”类型的环境的高资源利用效率低,所以不这样做,在现实生活中有着密切的联系。 :)

希望这会有所帮助。

+0

嗨迈克,谢谢你的帮助。 当我用上面提供的代码替换相应的代码时,会创建四个线程并很快出现,输出结果就是“hello world”。 所以我觉得可能会有一些错误的主要方法,真的,我忘了补充join方法,所以我跑终止的主要方法,而其他三个线程仍然活着的风险。 将pthread_join()添加到主方法的末尾,错误不再发生。 嗯,我是多线程编程的新手,你的回复让我想起了加入方法,谢谢。 – user188916 2009-12-17 03:16:02

+0

以及即时通讯尝试在我的另一个测试源上使用你的建议,但一旦它运行mysql说“太多连接”,你有更好的主意吗? – capede 2011-06-18 18:19:46

1

的问题是,您所呼叫mysql_library_end()太早(尤其是在线程usleep()函式)。可以完成主线程并让其他线程继续工作,但不建议这样做。添加pthread_join()的解决方案是最好的。你也可以消除mysql_library_end(),它会起作用。