2009-12-16 3 views
0

Я написал простую многопоточную программу C для доступа к MySQL, она отлично работает, кроме , когда я добавляю функцию usleep() или sleep() в каждой функции потока. я создал два Pthreads в главном методе,многопоточный доступ Ошибка 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. 

и когда я добавить pthread_mutex_lock в функции addRecord_d, ошибка все еще существует. Так в чем же проблема?

ответ

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

Привет, Майк, спасибо вам за помощь. Когда я заменяю соответствующий код на те, которые вы указали выше, четыре потока создаются и существуют в ближайшее время, выход - это просто «мир привет». , поэтому я думаю, что может быть некоторая ошибка в основном методе, действительно, я забыл добавить метод join, поэтому я запускаю риск прекращения основного метода, в то время как остальные три потока все еще живы. Добавьте pthread_join() в конец основного метода, ошибка больше не будет возникать. Ну, я новичок в многопоточном программировании, и ваш ответ напоминает мне метод соединения, спасибо. – user188916

+0

Ну, я пытаюсь использовать ваш совет на другом тестовом источнике, но как только он запустил mysql, он сказал «Слишком много соединений», есть ли у вас идея лучше, чем эта? – capede

1

Проблема в том, что вы слишком рано вызываете mysql_library_end() (особенно с помощью usleep() в потоках). Можно закончить основной поток и продолжить работу других потоков, но это не рекомендуется. Ваше решение добавить pthread_join() является лучшим. Вы также можете устранить mysql_library_end(), и он будет работать.

Смежные вопросы