线程的控制

  1. 线程的创建:

    线程创建函数:int pthread_create(pthread_t *thread,const pthread_attr_t *attr,void *(*start_routine(void*),void *arg);

    返回值:成功返回0,失败返回错误号。

    在一个线程中调用pthread_create()创建新的线程后,当前线程从pthread_create()返回继续往下执行,而新的线程所执行的代码由我们传给pthread_create()的函数指针star_routine决定。pthread_create成功返回后,新创建的线程id被填写到thread参数所指向的内存单元。线程id的类型是thread_t,它只在当前进程中保证是唯一的,在不同的系统中thread_t这个类型有不同的实现,它可能是一个整数值,也可能是一个结构体,也可能是一个地址,用pthread_self()可获得当前线程id

    如果任意一个线程调用了exit_exit,则整个进程的所有线程都终止。

  2. 线程的终止:

    有以下三种方法终止线程:

                   从线程函数return,这种方法对主线程不适用,从main函数return相当于调用exit

         一个线程可以调用pthread_cancel终止统一进程中的另一个线程;

         程可以调用pthread_exit终自己;


下面我们看一段代码,看看这3中方法的区别:

  #include <stdlib.h>

  #include <unistd.h>

  #include <pthread.h>

  #include <sys/types.h>                                                                                                                                              


  void *thread1(void *arg)

  {

      printf("thread 1 returning....\n");

      return (void*)1;

  }

  void *thread2(void *arg)

  {

      printf("thread 1 exiting....\n");

      pthread_exit((void*)2);

  }

  void *thread3(void *arg)

  {

      while(1)

      {

          printf("thread 3 is runing,wait to bu cancel...\n");

          sleep(1);

      }

      return NULL;

 }

  

  

  int main()

  {

      pthread_t tid;

      void *val;

  

     pthread_create(&tid,NULL,thread1,NULL);

     pthread_join(tid,&val);

     printf("thread return,thread id is:%u,return code is:%d\n",tid,(int)val);

 

     pthread_create(&tid,NULL,thread2,NULL);

     pthread_join(tid,&val);

     printf("thread exit,thread id is:%u,exit code is:%d\n",tid,(int)val);

 

     pthread_create(&tid,NULL,thread3,NULL);

     sleep(3);

     pthread_cancel(tid);                                                                                                                                 

     pthread_join(tid,&val);

     printf("thread return,thread id is:%u,return code is:%d\n",tid,(int)val);

     return 0;

 }

运行结果如下:

 wKioL1cTTPrhcq-pAAA0yQJRJrk267.png

     一般情况下,线程终止后,其状态一直保留到其他线程调用pthread_join获取它的状态为止,但是线程也可以被置为detach状态,这样的线程一旦终止,就立刻回收它所占有的所有资源,而不保留终止状态,不能对一个处于detach状态的线程调用pthread_join,这样的调用将返回EINVAL,对一个尚未detach的线程调用pthread_joinpthread_detach都可以把该线程置为detach状态。也就是说不能对一个线程调用两次pthread_join 或者已经对一个线程调用了pthread_detach,就不能再调用pthread_join了。

 

线程分离

在任何一个时间点上,线程是可结合的或者是可分离的,一个可结合的线程能够被其他线程收回其资源和杀死,在被其他线程收回之前,它的存储资源是不释放的。相反,一个分离的线程是不能被其他线程回收或杀死的,他的存储器资源在它终止时由系统自动释放。

默认情况下,线程被创建成可结合的,为了避免存储器泄露,每个可结合线程要么被显示的回收,要么调用pthread_detach函数被分离。

由于调用pthread_join后,如果该线程没有运行结束,调用者会被阻塞,我们并不希望如此。我们这时可以在子线程代码中加入pthread_detachpthread_self())或者父线程调用pthread_detachtid).这将子线程的状态设置为分离的,该线程运行结束后会自动释放所有资源。

下面我们看一段代码:

 #include <stdio.h>

 #include <stdlib.h>

 #include <unistd.h>

 #include <pthread.h>

 #include <sys/types.h>

                                                                                                                                                                     

 void *thread(void *arg)

 {

     pthread_detach(pthread_self());

     printf("thread 1 returning....\n");

     return NULL;

}

 

 int main()

{

     pthread_t tid;

     int ret=pthread_create(&tid,NULL,thread,NULL);

     if(ret!=0)

     {

         printf("create thread error,info is :%s\n",strerror(ret));

     }

     sleep(1);

     if(0==pthread_join(tid,NULL))

     {

         printf("thread wait success\n");

     }

     else

     {

         printf("thread wait failed\n");

     }

     return 0;

 }

运行结果:

  wKioL1cTTXGxVUGqAAAbgKbIXt8361.png

从结果可以看到,我们在子线程里面用了pthread_detach,在主线程里面又用了pthread_join,所以会wait failed