2009-12-16 53 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(),它會起作用。