linux程式設計——多線程(第十二章)

來源:互聯網
上載者:User

標籤:ubi   nis   相對   src   success   http   div   執行   stdio.h   

12.8    多線程之前,總是讓程式的主線程只建立一個線程。這節將示範怎樣在同一個程式中建立多個線程,然後怎樣以不同於其啟動順序將它們合并在一起。此外,還 示範多線程編程時easy出現的時序問題.
編敲代碼thread8.c
/************************************************************************* > File Name:    thread8.c > Description:  thread8.c程式建立多個線程。然後以不同於啟動順序將它們合并在一起 > Author:       Liubingbing > Created Time: 2015年07月07日 星期二 19時37分45秒 > Other:        thread8.c程式存在一個小漏洞,假設主線程執行足夠快時,可能改動傳遞引用的參數thread_index,造成問題.見thread8a.c ************************************************************************/#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <pthread.h>#define NUM_THREADS 6void *thread_function(void *arg);int main(){int res;pthread_t a_thread[NUM_THREADS];void *thread_result;int thread_index;for (thread_index = 0; thread_index < NUM_THREADS; thread_index++) {/* pthread_create建立新線程,這裡建立了一個線程ID的數組 */res = pthread_create(&(a_thread[thread_index]), NULL, thread_function, (void *)&thread_index);if (res != 0) {perror("Thread creation failed");exit(EXIT_FAILURE);}sleep(1);}printf("Waiting for threads to finish...\n");/* 主線程中等待合并這些子線程,但並非以建立它們的順序來合并 */for (thread_index = NUM_THREADS - 1; thread_index >= 0; thread_index--) {res = pthread_join(a_thread[thread_index], &thread_result);if (res == 0) {printf("Picked up a thread\n");} else {perror("pthread_join failed");}}printf("All done\n");exit(EXIT_SUCCESS);}void *thread_function(void *arg) {int my_number = *(int *)arg;int rand_num;printf("thread_function is running. Argument was %d\n", my_number);/* 建立的線程等待一段隨機的時間退出執行 */rand_num = 1 + (int)(9.0 * rand() / (RAND_MAX + 1.0));sleep(rand_num);printf("Bye from %d\n", my_number);pthread_exit(NULL);}
執行thread8.c,看到例如以下結果:


這個程式首先建立一個線程ID的數組。例如以下所看到的:
pthread_t a_thread[NUM_THREADS];
然後通過迴圈建立多個線程。例如以下所看到的:
for (thread_index = 0; thread_index < NUM_THREADS; thread_index++) {    res = pthread_create(&(a_thread[thread_index]), NULL, thread_function, (void *)&thread_index);}
建立出的線程等待一段隨機的時間後退出執行,例如以下所看到的:
void *thread_function(void *arg) {    int my_number = *(int *) arg;    int rand_num;    printf("thread_function is running. Argument was %d\n", my_number);    rand_num = 1 + (int)(9.0 * rand() / RAND_MAX + 1.0));    sleep(rand_num);    printf("Bye from %d\n", my_number);    pthread_exit(NULL);}
在主線程中。等待合并這些子線程。但並非以建立它們的順序來合并。例如以下所看到的:
for (thread_index = NUM_THREADS -1; thread_index >= 0; thread_index--) {    res = pthread_join(a_thread[thread_index], &thread_result);    ... }
這個程式有一個小漏洞,假設將sleep調用從啟動線程的迴圈中刪除,它將會變得非常明顯。

非常可能會看到一些奇怪的現象,比方一些線程以同樣的參數被啟動,類似:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" >
為什麼會出現這種問題?啟動線程時,線程函數的參數是一個局部變數,這個變數在迴圈中被更新。引起問題的程式碼是:

for (thread_index = 0; thread_index < NUM_THREADS; thread_index++) {    res = pthread_create(&(a_thread[thread_index]), NULL, thread_function, (void *)&thread_index);}
假設主線程執行的足夠快(由於刪除sleep(1)之後,主線程相對新線程就很快了),就可能改變某些線程的參數(即thread_index)。

此時,傳遞引用不是恰當的選擇,而傳值是正確的.當對共用變數和多個執行路徑沒有做到足夠重視時,程式就可能出現這種錯誤行為。

編寫線程程式時須要在設計上特別小心。

要改正這個問題。能夠直接傳遞給這個參數的值,例如以下所看到的:

res = pthread_create(&(a_thread[thread_index]), NULL, thread_function, (void *)thread_index);
還有改動thread_function函數,例如以下所看到的:
int my_number = (int) arg;

linux程式設計——多線程(第十二章)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.