【Linux】linux线程--pthread_线程控制

目录

1.线程创建

2.线程终止

3.线程等待

4.线程分离


1.线程创建

int  pthread_create(pthread_t  *thread , const  pthread  *attr , void  *(*start_routine)(void  *) , void  *arg);

头文件:

     pthread.h

参数:

     thread:获取线程标识符(地址),本质上就是线程独有空间的首地址

     attr:线程的属性信息,一般填写NULL,采用默认的线程属性

     start_routine:函数指针,线程执行的入口函数(线程执行起来的时候,从该函数开始运行,切记:不是从main函数开始运行)

     arg:给线程入口函数传递参数

返回值:

     成功返回0,失败返回值<0

代码举例:

    1 #include<stdio.h>
    2 #include<pthread.h>
    3 #include<unistd.h>
    4 void* mythread_start(void* arg){
    5   while(1){
    6     printf("i am my_thread_start\n");
    7     sleep(1);
    8   }
    9   return NULL;                                                  
   10 }
   11 int main(){
   12   pthread_t tid;
   13   int ret=pthread_create(&tid,NULL,mythread_start,NULL);
   14   if(ret<0){
   15     perror("pthread_create\n");
   16     return 0;
   17   }
   18   printf("success...\n");
   19   return 0;
   20 }

运行结果如下:

说明创建成功了,但是为什么工作线程没有继续运行呢

是因为主线程输出success之后就推出了,工作线程自然无法工作。

只要把主线程写进循环不让他那么早的退出,就能够观察到工作线程的工作状况。

    1 #include<stdio.h>
    2 #include<pthread.h>
    3 #include<unistd.h>
    4 void* mythread_start(void* arg){
    5   while(1){
    6     printf("i am my_thread_start\n");
    7     sleep(1);
    8   }
    9   return NULL;
   10 }
   11 int main(){
   12   pthread_t tid;
   13   int ret=pthread_create(&tid,NULL,mythread_start,NULL);
   14   if(ret<0){
   15     perror("pthread_create\n");
   16     return 0;
   17   }
   18   while(1){
   19     printf("success...\n");
   20     sleep(1);                                                   
   21   }
   22   return 0;
   23 }

运行结果如下:

 分析一下线程的堆栈信息:

结论:

(1)当创建完毕线程之后,主线程和工作线程都是独立被调度的。引申含义是:没有办法确定到底是先调用主线程还是工作线程,由操作系统调度决定的。

(2)如果创建工作线程完毕之后,但是,进程退出了,有可能看不到工作线程运行的结果。原因就是:没有了进程,就不肯拥有更改创建出来的工作线程。

(3)如果想看到工作线程的运行结果,则先保证进程不退出。如果想让工作线程不退出,则线程不能执行线程入口函数完毕。

(4)pstack查看线程信息。

是否可以创建多个线程(多线程)?

答案是肯定的,代码编写也很简单:

    1 #include<stdio.h>
    2 #include<pthread.h>
    3 #include<unistd.h>
    4 void* mythread_start(void* arg){
    5   while(1){
    6     printf("i am my_thread_start\n");
    7     sleep(1);
    8   }
    9   return NULL;
   10 }
   11 int main(){
   12   pthread_t tid;
   13   int ret=pthread_create(&tid,NULL,mythread_start,NULL);
   14   if(ret<0){
   15     perror("pthread_create\n");
   16     return 0;
   17   }
   18   ret=pthread_create(&tid,NULL,mythread_start,NULL);            
   19   if(ret<0){
   20     perror("pthread_create\n");
   21     return 0;
   22    }
   23   while(1){
   24     printf("success...\n");
   25     sleep(1);
   26   }

运行结果如下:

正儿八经的确实创建出来了两个工作线程。,这两个线程执行的入口函数是同一个。

 这两个线程看到的mythread_start栈帧是不是同一个呢?

答案肯定是不是的,利用工厂与流水线的关系也可以看出,不同的流水线完全可以执行不同的工作,如果所有流水线都是同一个的镜像,这样就失去了多线程的意义。

咱们再用for循环来批量生产工作线程:

  1 #include<stdio.h>
  2 #include<pthread.h>
  3 #include<unistd.h>
  4 void* mythread_start(void* arg){
  5   int* i =(int*)arg ;
  6   while(1){
  7     printf("i am workthread... %d\n",*i);
  8     sleep(1);
  9   }
 10   return NULL;
 11 }
 12 int main(){
 13   int i;
 14   for(i=0;i<4;i++){
 15     pthread_t tid;
 16     int ret=pthread_create(&tid,NULL,mythread_start,&i);
 17     if(ret<0){
 18     perror("pthread_create\n");
 19     return 0;
 20     }
 21   }
 22   while(1){
 23     printf("success...\n");
 24     sleep(1);
 25   }
 26   return 0;
 27 }

观察一下运行结果:

 很乱啊,为什么会出现这种情况;

换句话说为什么再之后的工作线程当中打印的i都是4呢。

因为函数中传递的入口空间一直都是i的地址,而i只是主函数中的一个循环变量,打印的始终都是i这个临时变量的地址空间,当i变成4之后,四个工作线程打印的自然都是4了。

这样运用循环来批量制造工作线程有风险码?

当然有,表现是多个线程在访问的i的空间是非法访问,因为i是临时变量,除了for循环的作用域之后就被销毁了。

结论:线程入口函数的参数不要传递临时变量,临时变量出了作用域之后就会被销毁。有可能线程在非法访问空间。

如何避免4444这种情况:

(1)各个线程直接打印自己的线程标识符pthread_self;

(2)给线程分别传递不同的堆上空间。

总结:

(1)线程入口函数传递参数的时候,传递堆栈空间;

(2)释放堆区空间的时候,让线程自己进行释放。

2.线程终止

void  pthread_exit(void  *retval);

参数:

     retval:线程退出时,传递给等待线程的退出信息。

作用:

     谁调用就由谁退出

int  pthread_cancel(pthread_t  thread);

参数:

     thread:被终止的线程的标识符

作用:退出某个线程

3.线程等待

线程被创建出来的默认属性是joinable属性,退出的时候,依赖其他线程来回收资源(主要是退出线程使用到的共享区当中的空间)。

int  pthread_join(pthread_t  thread , void  **retval);

参数:

     thread:线程的标识符

     retval:退出线程的退出信息

第一种:线程入口函数代码执行完毕,线程退出的,就是入口函数的返回值;

第二种:pthread_exit退出的,就是pthread_exit的参数;

第三组:pthread_cancel退出的,就是一个宏:OTHREAD_CANCELED。

4.线程分离

设置线程的分离属性,一旦线程设置了分离属性,则线程退出的时候,不需要任何人回收资源,操作系统可以自行回收。

int  pthread_detach(pthread_t  thread);

参数:

     thread:设置线程分离的线程标识符。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值