歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Unix知識 >> Unix基礎知識 >> UNIX環境高級編程:pthread_create的問題

UNIX環境高級編程:pthread_create的問題

日期:2017/3/3 15:19:58   编辑:Unix基礎知識

linux 下常用的創建多線程函數pthread_create(pthread_t * thread , pthread_attr_t * attr , void *(*start_routine)(void*) , void *args);

其中第一個參數用來保存線程信息,第二個參數指新線程的運行屬性,可以設置為NULL,第三個參數為自定義的線程函數,第四個參數就是線程函數需要用到的參數,一般如果要傳遞多個參數,可以設置為結構體(struct)類型,這裡我們使用int類型的變量。

下面我著重討論一個用for結構來創建多個線程時參數傳遞的問題:

#include <stdio.h>  
#include <stdlib.h>  
#include <pthread.h>  
      
      
#define th_pop 20   
      
pthread_mutex_t mutex;  
      
pthread_t a_thread[th_pop];  
      
      
void * thread_func(void *args)  
{  
    pthread_mutex_lock(&mutex);  
    int t_id = *(int*)args;  
    printf("the id of this thread is %d\n",t_id);  
    pthread_mutex_unlock(&mutex);      
    return (void*)NULL;  
}  
      
void init()  
{  
    pthread_mutex_init(&mutex, NULL);  
    int i;  
    for( i=0; i<th_pop; i++)  
    {  
        pthread_create(&a_thread[i] , NULL , thread_func , &i);  
    }  
    //wait the end of the threads;  
    for( i=0; i<th_pop; i++)  
    {  
        int res = pthread_join(a_thread[i] , NULL);  
        if(res != 0)  
            printf("the thread id: %d ends fail \n",i);  
    }  
    pthread_mutex_destroy(&mutex);  
          
}  
      
int main()  
{  
    init();  
    return 0;  
}

運行結果:

huangcheng@ubuntu:~$ ./a.out
the id of this thread is 2  
the id of this thread is 8  
the id of this thread is 9  
the id of this thread is 9  
the id of this thread is 20  
the id of this thread is 20  
the id of this thread is 20  
the id of this thread is 20  
the id of this thread is 20  
the id of this thread is 20  
the id of this thread is 20  
the id of this thread is 20  
the id of this thread is 20  
the id of this thread is 20  
the id of this thread is 20  
the id of this thread is 20  
the id of this thread is 20  
the id of this thread is 20  
the id of this thread is 20  
the id of this thread is 20

看到這個結果有沒有感覺到有什麼不對呢?可能你會感覺到很納悶,怎麼出現了那麼多的id=0的結果呢?其實這個認真分析一下並不難理解:

首先pthread_create函數傳遞的是一個指針型的參數,即傳遞的是一個地址而已,這樣在執行for結構時:

for(int i=0; i<th_pop; i++)  
{  
        pthread_create(&a_thread[i] , NULL , thread_func , &i);  
}

該for循環快速執行完成,並且將i置為20,故而傳遞的地址指向的內容為20,同時其它的線程還沒來得及執行: int t_id = *(int*)args;

查看本欄目更多精彩內容:http://www.bianceng.cn/OS/unix/

這樣就使得多個線程都指向同一個地址,內容為20,解決該問題的一個辦法為中for結構中加入sleep(1),這樣當sleep時間大於線程函數執行時間,就可以得到一個正確的結果,不過這種辦法剝掉了並發性,並不可取,下面我們采用另一種方法。

我們只修改init()函數

#include <stdio.h>  
#include <stdlib.h>  
#include <pthread.h>  
      
      
#define th_pop 20 //  
      
pthread_mutex_t mutex;  
      
pthread_t a_thread[th_pop];  
      
      
void * thread_func(void *args)  
{  
    pthread_mutex_lock(&mutex);  
    int t_id = *(int*)args;  
    printf("the id of this thread is %d\n",t_id);  
    pthread_mutex_unlock(&mutex);      
    return (void*)NULL;  
}  
      
void init()  
{  
    pthread_mutex_init(&mutex, NULL);  
    int thread_id[th_pop];  
    int i;  
    for( i=0; i<th_pop; i++)  
        thread_id[i] = i;  
    for( i=0; i<th_pop; i++)  
    {  
        int *t = thread_id +i;  
        pthread_create(&a_thread[i] , NULL , thread_func , (void*)t);  
    }  
    //wait the end of the threads;  
    for( i=0; i<th_pop; i++)  
    {  
        int res = pthread_join(a_thread[i] , NULL);  
        if(res != 0)  
            printf("the thread id: %d ends fail \n",i);  
    }  
    pthread_mutex_destroy(&mutex);  
          
}  
      
int main()  
{  
    init();  
    return 0;  
}

運行結果:

huangcheng@ubuntu:~$ ./a.out
the id of this thread is 3  
the id of this thread is 2  
the id of this thread is 1  
the id of this thread is 4  
the id of this thread is 5  
the id of this thread is 6  
the id of this thread is 7  
the id of this thread is 8  
the id of this thread is 9  
the id of this thread is 10  
the id of this thread is 11  
the id of this thread is 12  
the id of this thread is 13  
the id of this thread is 14  
the id of this thread is 15  
the id of this thread is 16  
the id of this thread is 17  
the id of this thread is 18  
the id of this thread is 19  
the id of this thread is 0

從這個例子中我們應該明白,要避免直接在傳遞的參數中傳遞發生改變的量,否則會導致結果不可測。

解決這類問題的辦法:

(1)復制一份到堆裡面。
(2)加鎖。(一般做法)
(3)用結構體數組。(推薦這個)
(4)sleep。(不推薦)

作者信息:csdn博客 ctthuangcheng

Copyright © Linux教程網 All Rights Reserved