線程程序示例

一、創建一個線程,並回收,驗證線程是全局變量共享的

#include<stdio.h>
#include<unistd.h>
#include<pthread.h>
//exit()在這個庫中
#include<stdlib.h>
//線程函數
void* ptf(void* arg)
{
    printf("this is child pthread!,pthread_id is %lu\n",pthread_self());
    //return NULL;
    pthread_exit(NULL);
}
int main()
{
    pthread_t pt_id;
    //用於存放線程建立返回值
    int ret;
    ret=pthread_create(&pt_id,NULL,ptf,NULL);
    //pt_id,會在創建好線程後,賦值,同時驗證了線程全局變量共享
    printf("child pthread id is %lu\n",pt_id);
    if(ret!=0)
    {
        printf("create child  pthread error!\n");
        exit(1);
    }
    //阻塞等待
    pthread_join(pt_id,NULL);
    printf("process id is %u\n",getpid());
    return 0;
    //pthread_exit((void*)1);
}

二、創建一個線程,子線程設置參數, 父線程回收


#include<stdio.h>
#include<unistd.h>
#include<pthread.h>
//exit()在這個庫中
#include<stdlib.h>
typedef struct{
    int a;
    char b;
}exit_t;

void* ptf(void* arg)
{
    printf("this is child pthread!,pthread_id is %lu\n",pthread_self());
    exit_t*ret=(exit_t*)malloc(sizeof(exit_t));
    ret->a=100;
    ret->b='b';
    //return NULL;
    //強制轉換成void*
    pthread_exit((void*)ret);
}
int main()
{
    pthread_t pt_id;
    exit_t*retval=NULL;
    int ret;
    ret=pthread_create(&pt_id,NULL,ptf,NULL);
    
    if(ret!=0)
    {
        printf("create child  pthread error!\n");
        exit(1);
    }
    //sleep(1);
    //強制轉換成void**,因爲pthread_exit返回的是void*
    pthread_join(pt_id,(void**)&retval);
    printf("process id is %u\n",getpid());
    printf("a is %d,b is %c\n",retval->a,retval->b);
    
    free(retval);
    pthread_exit((void*)1);
    //return 0;
}

 三、回收多個子進程


/*回收多個子線程*/                                                           
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>

int var=100;

void *tfn(void *arg)  //每個子線程進行回收
{
    int i;
    i = (int)arg;

    sleep(i);  //輸出有順序
    if(i == 1){
        var = 333;
        printf("var = %d\n",var);
        return (void *)var;

    }else if(i == 3){

        var = 777;
        printf("I'm %d th 線程,線程ID爲 %lu var = %d\n",i+1,pthread_self(),var);
        pthread_exit((void *)var);
    }else {

        printf("I'm %d th 線程,線程ID = %lu\n var = %d\n",i+1,pthread_self(),var);
        pthread_exit((void *)var);
    }
    
    return NULL;
}

int main(void)
{
    pthread_t tid[5];
    int i;
    int *ret[5]; //保存 5個線程的退出值

    for(i = 0;i < 5; i++)//循環創建多個子線程
        pthread_create(&tid[i],NULL,tfn,(void*)i);

    for(i=0;i < 5; i++){ //對多個子線程進行回收
        pthread_join(tid[i],(void **)&ret[i]);
        printf("-----------%d th ret = %d\n",i,(int)ret[i]);
    }
    printf("I'm main 線程 tid = %lu\t var = %d\n",pthread_self(),var);
    //主控線程也打印777,原因是共享全局變量
    sleep(i);
    return 0;
}                 
#include<stdio.h>
#include<unistd.h>
#include<pthread.h>
//exit()在這個庫中
#include<stdlib.h>
#define n 5
int val;


void* ptf(void* arg)
{
    int i;
    i=(int)arg;
    printf("i is %d\n",i);
    
    val=100;
    //sleep(i);
    if(i<3)
    {
        //printf("this is child pthread!,pthread_id is %lu\n",pthread_self());
        val=33;
        //printf("a is %d,b is %c\n",ret->a,ret->b);
        
    }
    else
    {
        //printf("this is child pthread!,pthread_id is %lu\n",pthread_self());
        val=44;  
         
    }

    //return NULL;
    //強制轉換成void*
    pthread_exit((void*)val); 
}
int main()
{
    pthread_t pt_id[n];

    int *ret[n];
    int i;
    //創建多個線程,速度太快,相當於同時創建多個進程
    for(i=0;i<n;i++)
    {
        //sleep(i);
        //(void*)i 傳遞的是i的值,強制轉化成void*,傳地址的話沒有上鎖可能會產生多線程競爭
        pthread_create(&pt_id[i],NULL,ptf,(void*)i);

    }
    for(i=0;i<n;i++)
    {
        //強制轉換成void**,因爲pthread_exit返回的是void*
        pthread_join(pt_id[i],(void**)&ret[i]);
        printf("a is %d\n",ret[i]);
        
    }
    pthread_exit((void*)1);
    //return 0;
}

 四、線程分離

#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<pthread.h>

void *tfn(void *arg)
{
    int n=3;
    
    while(n--){
        printf("thread count %d\n",n);
        sleep(1);
    }   

    return (void *)1;
}

int main(void)
{
    pthread_t tid;
    void *tret;
    int err;
    
    pthread_create(&tid,NULL,tfn,NULL);
    pthread_detach(tid);        //讓線程分離   ----自動退出,無系統殘留資源
    
    while(1){
        //因爲線程分離,無需回收,所以阻塞等待返回錯誤代碼
        err = pthread_join(tid,&tret);
        printf("---------err= %d\n",err);
        if(err != 0)
            //根據錯誤代碼打印錯誤
            fprintf(stderr,"thread error: %s\n",strerror(err));              
        else
            fprintf(stderr,"thread exit code %d\n",(int)tret);

        sleep(1);
    }       
    return 0;
}

五、殺死線程,如果線程函數沒有系統調用函數的取消點,則必須自己添加取消點,才能殺死,printf底層調用了read函數,sleep底層調用了pause函數


/*三種退出線程的方法*/                                                       

#include<stdio.h>
#include<string.h>
#include<pthread.h>

void *tfn1(void *arg)  //第一個線程
{
    printf("thread 1 returning\n");

    return (void *)111;
}

void *tfn2(void *arg)   //第二個線程
{
    printf("thread 2 exiting\n");

    pthread_exit((void *)222);
}

void *tfn3(void *arg)   //第三個線程
{
    while(1){
        printf("thread 3:I'm going to die in 3 seconds ....\n");
        sleep(1);

        //pthread_testcancel();//自己添加取消點
    }
    return (void *)666;
}

int main(void)
{
    pthread_t tid;
    void *tret = NULL;

    pthread_create(&tid,NULL,tfn1,NULL);
    pthread_join(tid,&tret);
    printf("thread 1 exit code = %d\n\n",(int)tret);

    pthread_create(&tid,NULL,tfn2,NULL);
    pthread_join(tid,&tret);
    printf("thread 2 exit code = %d\n\n",(int)tret);

    pthread_create(&tid,NULL,tfn3,NULL);
    sleep(3);
    pthread_cancel(tid);
    pthread_join(tid,&tret);
    printf("thread 3 exit code = %d\n\n",(int)tret);

    return 0;
}        

六、手動初始化線程屬性,設置分離狀態,必須先初始化線程


#include<stdio.h>                                                            
#include<unistd.h>
#include<string.h>
#include<pthread.h>

void *tfn(void *arg)
{
    int n=3;
    
    while(n--){
        printf("thread count %d\n",n);
        sleep(1);
    }

    return (void *)1;
}

int main(void)
{
    pthread_t tid;
    void *tret;
    int err;
 
#if 1
    pthread_attr_t attr;  //通過線程屬性類設置遊離態
    //必須先初始化
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    pthread_create(&tid,&attr,tfn,NULL);

#else
    pthread_create(&tid,NULL,tfn,NULL);
    pthread_detach(tid);        //讓線程分離   ----自動退出,無系統殘留資源
#endif
    while(1){
        err = pthread_join(tid,&tret);
        printf("---------err= %d\n",err);
        if(err != 0)
            fprintf(stderr,"thread error: %s\n",strerror(err));
    else
            fprintf(stderr,"thread exit code %d\n",(int)tret);

        sleep(1);
    }
    return 0;
}              

 七、設置線程棧的大小,設置線程屬性的綜合實例


#include<stdio.h>                                                            
#include<unistd.h>
#include<pthread.h>
#include<string.h>
#include<stdlib.h>

#define SIZE 0x100000

void *th_fun(void * arg)
{
    while(1);
    sleep(1);
}

int main(void)
{
    pthread_t tid;
    int err, detachstate,i=1;
    pthread_attr_t attr;
    size_t stacksize;
    void *stackaddr;

    pthread_attr_init(&attr);
    pthread_attr_getstack(&attr,&stackaddr,&stacksize);
    pthread_attr_getdetachstate(&attr,&detachstate);

    if(detachstate == PTHREAD_CREATE_DETACHED)//默認是分離態
        printf("thread detached\n");
    else if(detachstate == PTHREAD_CREATE_JOINABLE)//默認非分離
        printf("thread join\n");
    else
        printf("thread un known\n");

    //設置線程分離
    pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);

    while(1){
        //在堆上申請內存,指定線程棧的起始地址和大小
        stackaddr = malloc(SIZE);
            if(stackaddr == NULL){
            perror("malloc");
            exit(1);
        }
        stacksize = SIZE;
        pthread_attr_setstack(&attr,stackaddr,stacksize);//藉助線程的屬性,修
改線程棧空間大小

        err = pthread_create(&tid,&attr,th_fun,NULL);
        if(err != 0){
            printf("%s\n",strerror(err));
            exit(1);
        }
        printf("%d\n",i++);//i表示循環創建多少次
    }

    pthread_attr_destroy(&attr);

    return 0;
}       

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章