線程 屬性、取消線程、多線程

12.6 線程的屬性:
    線程建立後,在程序退出以前咱們能夠經過pthread_join再次與線程同步,在結束的時候向主線程返回一些數據。有時候咱們不須要線程結束的時候向主線程返回數據,也不須要主線程等待他的結束,這一類型的線程叫作脫離線程。能夠經過修改線程的屬性或者pthread_deatch的方法來建立它們。
    線程屬性最重要的函數就是pthread_attr_init,它的做用是初始化一個線程屬性對象。
#include  <pthread.h>
int pthread_attr_init(pthread_attr_t *attr);
    與前面同樣,該函數成功時返回0,失敗時返回錯誤代碼。
    還有一個回收函數pthread_attr_destory,它的目的是對屬性對象進行清理和回收,一旦對象回收 了,除非從新被初始化,否者不能再使用。
    初始化一個線程對象後,咱們就能夠調用其餘的函數來設置不一樣的屬性行爲。主要的函數以下:多線程

 1 #include<pthread.h>
 2 int pthread_attr_setdetachstate(pthread_attr_t* attr,int detachstate);
 3 int pthread_attr_getdetachstate(const pthread_attr_t* attr,int detachstate);
 4 int pthread_attr_setschedpolicy(pthread_attr_t*attr,int policy);
 5 int pthread_attr_getschegpolicy(const pthread_attr_t* attr,int policy);
 6 int pthread_attr_setschedparam(pthread_attr_t* attr,struct sched_param* param);
 7 int pthread_attr_getschedparam(const pthread_attr_t* attr,struct sched_param* param);
 8 int pthread_attr_setinheritsched(pthead_attr_t* attr, int inherit);
 9 int pthread_attr_getinheritsched(const pthread_attr_t* attr,int* inhert);
10 int pthread_attr_setscope(pthread_attr_t* attr,int scope);
11 int pthread_attr_getscope(const pthread_attr_t* attr ,int * scope);
12 int pthread_attr_setstacksize(pthread_attr_t* attr,int scope);
13 int pthread_attr_getstacksize(const pthread_attr_t* attr,int* scope);

 


    可見線程可使用的屬性不少,可是一般不須要設置太多的屬性就能夠正常工做。
       ❑ detachedstate:這個屬性容許咱們無需對線程進行從新合併。與大多數_set類函數同樣,它以一個屬性指針和一個標誌爲參數來肯定須要的狀態。pthread_attr_setdetachstate函數可能用到的兩個標誌分別是PTHREAD_CREATE_JOINABLE和PTHREAD_CREATE_DETACHED。這個屬性的默認標誌值是PTHREAD_CREATE_JOINABLE,因此能夠容許兩個線程從新合併。若是標誌設置爲PTHREAD_CREATE_DETACHED,就不能調用pthread_join來得到另外一個線程的退出狀態。
      ❑ schedpolicy:這個屬性控制線程的調度方式。它的取值能夠是SCHED_OTHER、SCHED_RP和SCHED_FIFO。這個屬性的默認值爲SCHED_OTHER。另外兩種調度方式只能用於以超級用戶權限運行的進程,由於它們都具有實時調度的功能,但在行爲上略有區別。SCHED_RP使用循環(round-robin)調度機制,而SCHED_FIFO使用「先進先出」策略。
      ❑ schedparam:這個屬性是和schedpolicy屬性結合使用的,它能夠對以SCHED_OTHER策略運行的線程的調度進行控制。
      ❑ inheritsched:這個屬性可取兩個值:PTHREAD_EXPLICIT_SCHED和PTHREAD_INHERIT_SCHED。它的默認取值是PTHREAD_EXPLICIT_SCHED,表示調度由屬性明確地設置。若是把它設置爲PTHREAD_INHERIT_SCHED,新線程將沿用其建立者所使用的參數。
      ❑ scope:這個屬性控制一個線程調度的計算方式。
        ❑ stacksize:這個屬性控制線程建立的棧大小,單位爲字節。它屬於POSIX規範中的「可選」部分,只有在定義了宏_POSIX_THREAD_ATTR_STACKSIZE的實現版本中才支持。Linux在實現線程時,默認使用的棧很大,因此這個功能對Linux來講顯得有些多餘。
      實驗:脫離線程
//建立脫離線程,函數

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>void* thread_function(void* arg);
char message[]={"Hello thread!"};
int thread_finished=0;
​
int main()
{
    pthread_t a_thread;
    int res;
    pthread_attr_t pattr;
    //初始化屬性
    res=pthread_attr_init(&pattr);
    if(res!=0)
    {
        perror("Init threadattr failed");
        exit(EXIT_FAILURE);
    }
    //設置屬性
    res=pthread_attr_setdetachstate(&pattr,PTHREAD_CREATE_DETACHED);
    if(res!=0)
    {
        perror("Setting attr failed");
        exit(EXIT_FAILURE);
    }
    //建立線程
    res=pthread_create(&a_thread,&pattr,thread_function,(void*)message);
    if(res!=0)
    {
        perror("Create thread failed");
        exit(EXIT_FAILURE);
    }
    //屬性使用完畢後釋放資源
    (void)pthread_attr_destroy(&pattr);
    //循環,等待新線程設置結束標準;這裏代表主線程和其餘線程共享全局變量。
    
    while(thread_finished!=1)
    {
        printf("Wating for thread finished\n");
        sleep(1);
    }
    printf("other thread finished\n");
    exit(EXIT_SUCCESS);
    return 0;
}
​
void* thread_function(void*arg)
{
    printf("Thread is running.\nArgument is :%s\n",(char*)arg);
    sleep(1);
    printf("Second thread setting finished flag,and exiting now\n");
    thread_finished=1;
    pthread_exit(NULL);
}

 


線程屬性:調度
    另一個可能須要修改的屬性:調度。改變調度屬性和設置脫離狀態很是相似,可使用sched_get_priority_max和sched_get_priority_min這兩個屬性來差早可用的優先級別。
    實驗:調度ui

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>void* thread_function(void* arg);
char message[]={"Hello thread!"};
int thread_finished=0;
int main()
{
    int max_policy;
    int min_policy;
    struct sched_param sched_value;
    pthread_t a_thread;
    int res;
    pthread_attr_t pattr;
    //初始化屬性
    res=pthread_attr_init(&pattr);
    if(res!=0)
    {
        perror("Init threadattr failed");
        exit(EXIT_FAILURE);
    }
    //設置脫離屬性
    res=pthread_attr_setdetachstate(&pattr,PTHREAD_CREATE_DETACHED);
    if(res!=0)
    {
        perror("Setting attr failed");
        exit(EXIT_FAILURE);
    }
    //設置調度策略
    res=pthread_attr_setschedpolicy(&pattr,SCHED_OTHER);
    if(res!=0)
    {
        perror("Set sched failed");
        exit(EXIT_FAILURE);
    }
    //查找可以使用的優先級
    max_policy=sched_get_priority_max(SCHED_OTHER);
    min_policy=sched_get_priority_min(SCHED_OTHER);
    //設置優先級
    sched_value.sched_priority=min_policy;
    res=pthread_attr_setschedparam(&pattr,&sched_value);
    if(res!=0)
    {
        perror("Set sched attr failed");
        exit(EXIT_FAILURE);
    }
    //建立線程
    res=pthread_create(&a_thread,&pattr,thread_function,(void*)message);
    if(res!=0)
    {
        perror("Create thread failed");
        exit(EXIT_FAILURE);
    }
    (void)pthread_attr_destroy(&pattr);
    //循環,等待新線程設置結束標準;這裏代表主線程和其餘線程共享全局變量。
    
    while(thread_finished!=1)
    {
        printf("Wating for thread finished\n");
        sleep(1);
    }
    printf("other thread finished\n");
    exit(EXIT_SUCCESS);
    return 0;
}
void* thread_function(void*arg)
{
    printf("Thread is running.\nArgument is :%s\n",(char*)arg);
    sleep(4);
    printf("Second thread setting finished flag,and exiting now\n");
    thread_finished=1;
    pthread_exit(NULL);
}

 


七、取消一個線程:
    請求終止的函數:
    int pthread_cancle(pthread_t thread);提供一個進程標識符,就能夠終止它,在主線程是如此簡單,可是在被取消的線程是就不是這麼簡單了!!
    線程可使用pthread_setcanclestate設置本身的取消狀態:
    int pthread_setcanclestate(int state,int*oldstate);
    第一個參數能夠是PTHREAD_CANCLE_ENABLE這個值容許取消請求,PTHREAD_CANCLE_DISABLE,它的做用是忽略取消請求。oldstate指針用於獲取先前的狀態,沒有必要的時候能夠設置爲NULL; 若是取消請求被接受了,線程就能夠進入第二個控制層次,用pthread_setcanceltype設置取消類型。
    int pthread_setcancletype(int type,int* oldtype);
    type參數能夠有兩種取值:一個是PTHREAD_CANCEL_ASYNCHRONOUS(當即取消),它將使得在接收到取消請求後當即採起行動;另外一個是PTHREAD_CANCEL_DEFERRED(延遲取消),它將使得在接收到取消請求後,一直等待直到線程執行了下述函數之一後才採起行動。具體是函數pthread_join、pthread_cond_wait、pthread_cond_timedwait、pthread_testcancel、sem_wait或sigwait。
    實驗:取消一個線程spa

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>char message[]={"Hello thread!"};
void* thread_function(void*arg)
{
   int i,res;
   res=pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);//在新建立的線程中,咱們首先將取消狀態設置爲容許取消,
   if(res!=0)
   {
       perror("set cacle state failed");
       exit(EXIT_FAILURE);
   }
  res=pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,NULL);//而後將取消類型設置爲延遲取消
  //res=pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL);
   if(res!=0)
   {
       perror("set cancle type error");
       exit(EXIT_FAILURE);
   }
   printf("Thread_Function is runing\n");
    //最後,線程在循環中等待被取消
   for(i=0;i<10;i++)
   {
       printf("Thread is still runing\n");
       sleep(1);
   }
   pthread_exit(NULL);
}
​
int main()
{
    pthread_t a_thread;
    int res;
    void* thread_res;
    int i;
    //建立線程
    //以一般的方法建立了新線程後,主線程休眠一下子(好讓新線程有時間開始執行),而後發送一個取消請求。
    res=pthread_create(&a_thread,NULL,thread_function,NULL);
    if(res!=0)
    {
        perror("Create thread error");
        exit(EXIT_FAILURE);
    }
    sleep(3);
    printf("Canceling thread \n");
    res=pthread_cancel(a_thread);
    if(res!=0)
    {
        perror("cancel a thread failed");
        exit(EXIT_FAILURE);
    }
    printf("wating for thread to finish\n");
    if(res!=0)
    {
        perror("thread join failed");
        exit(EXIT_FAILURE);
    }
    exit(EXIT_SUCCESS);
}

 


多線程:線程

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>void* thread_function(void* arg)
{
     int my_number;
     int Rand;
    // my_number=(int)arg;
     my_number=*(int*)arg;
     printf("Thread_function runing from %d\n",my_number);
     Rand=1+(int)(9.0*rand()/(RAND_MAX+1.0));
​
     sleep(Rand);//休眠一個隨機時間
     printf("Bye from %d\n",my_number);
     pthread_exit(NULL);  
}
int main()
{
    int res;
    pthread_t thread_id[6];
    void * thread_res;
    int num_of_thread;
    for(num_of_thread=0;num_of_thread<6;num_of_thread++)
    {
        //res=pthread_create(&thread_id[num_of_thread],NULL,thread_function,(void*)num_of_thread);
        res=pthread_create(&thread_id[num_of_thread],NULL,thread_function,(void*)&num_of_thread);
        if(res==0)
        {
            sleep(1);
        }
        else
        {
            perror("Create thread fauiled");
            exit(EXIT_FAILURE);
        }
    }
    for(num_of_thread=5;num_of_thread>=0;num_of_thread--)
    {
        res=pthread_join(thread_id[num_of_thread],&thread_res);
        if(res==0)
        {
            printf("Picked ip a thread \n");
        }
        else
        {
            perror("Picedf up failed");
            exit(EXIT_FAILURE);
        }
    }
    printf("Picede upo all\n");
    printf("Done\n");
    exit(EXIT_SUCCESS);
}

 


       咱們建立了許多線程並讓它們以隨意的順序結束執行。這個程序有一個小漏洞,若是將sleep調用從啓動線程的循環中刪除,它就會變得很明顯。
        改進:指針

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <string.h>
 4 #include <unistd.h>
 5 #include <pthread.h>
 6  7 void* thread_function(void* arg)
 8 {
 9      int my_number;
10      int Rand;
11      my_number=(int)arg;
12      printf("Thread_function runing from %d\n",my_number);
13      Rand=1+(int)(9.0*rand()/(RAND_MAX+1.0));
14 15      sleep(Rand);//休眠一個隨機時間
16      printf("Bye from %d\n",my_number);
17      pthread_exit(NULL);  
18 }
19 int main()
20 {
21     int res;
22     pthread_t thread_id[6];
23     void * thread_res;
24     int num_of_thread;
25     for(num_of_thread=0;num_of_thread<6;num_of_thread++)
26     {
27         res=pthread_create(&thread_id[num_of_thread],NULL,thread_function,(void*)num_of_thread);
28         if(res!=0)
29         {
30             perror("Create thread fauiled");
31             exit(EXIT_FAILURE);
32         }
33     }
34     for(num_of_thread=5;num_of_thread>=0;num_of_thread--)
35     {
36         res=pthread_join(thread_id[num_of_thread],&thread_res);
37         if(res==0)
38         {
39             printf("Picked ip a thread \n");
40         }
41         else
42         {
43             perror("Picedf up failed");
44             exit(EXIT_FAILURE);
45         }
46     }
47     printf("Picede upo all\n");
48     printf("Done\n");
49     exit(EXIT_SUCCESS);
50 }
相關文章
相關標籤/搜索