繁体   English   中英

多线程访问MySQL错误

[英]multi-thread access MySQL error

我编写了一个简单的多线程C程序来访问MySQL,除了在每个线程函数中添加usleep()或sleep()函数外,它都能正常工作。 我在main方法中创建了两个pthread,

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时,错误仍然存​​在。 那么到底是什么问题呢?

问题是您调用mysql_library_end()的时间过早(尤其是在线程中使用usleep()时)。 可以完成主线程并让其他线程继续工作,但是不建议这样做。 您添加pthread_join()的解决方案是最好的。 您也可以消除mysql_library_end(),它将起作用。

当生产者线程和使用者线程休眠时,它们将保持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();
}

简而言之,以上示例应强制在睡眠周期之外建立并关闭连接。 我认为这不是最好的代码,但是出于您的说明目的,这应该消除错误。

请记住:这将迫使您以循环方式打开和关闭连接,这在“生产”类型的环境中资源的使用效率极低,因此请不要在现实生活中这么做。 :)

希望这可以帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM