线程

一、线程的基本概念

1、线程是在进程内部运行的一个执行分支
2、线程的创建成本比较小,删除进程成本也比较小,只需要创建一个PCB,指向那块内存地址空间就行。

这里写图片描述

这里写图片描述

3、线程是在进程内部运行,本质上是在同一块地址空间上运行。

怎么理解一个进程中间会有多个执行流的?

一个执行流被一个线程表示,一个进程里面可以有多个线程,所以一个进程里面会有多个执行流。
4、站在cpu的角度不需要区分进程与线程,因为cpu所做的工作很简单,就是去执行传递过来的指令

Linux cpu识别到的pcb或所看到的进程都可以识别为轻量级进程

进程是承担系统分配资源的一个基本实体。

线程是cpu调度的一个基本单位。

设置进程就是为了强调资源独占,设置线程就是为了体现资源共享,

这里写图片描述

5、每个线程都有自己的私有栈结构,每个线程都有自己的上下文信息

进程和线程的区别:

  • 1、进程是资源竞争的基本单位

  • 2、线程是程序执⾏行的最⼩小单位

  • 3、线程共享进程数据,但也拥有⾃自⼰己的⼀一部分数据: >* 线程ID >* ⼀一组寄存器 >* 栈 >* errno >* 信号 屏蔽字 >* 调度优先级

由于同一进程的多个线程共享同一块地址空间,因此Text Segment、Data Segegment、Data Segement都是共享的,如果定义一个函数,在各线程中都可以调用,如果定义一个全局变量,在各线程中都可以访问到,除此之外,各线程还共享以下进程资源和环境:

  • 1、文件描述符表
  • 2、每种信号的处理方式(SIG_IGN、SIG_DFL或者自定义的信号处理函数)
  • 3、当前工作目录
  • 4、用户id和组id

以下资源是每个线程各有一份:

  • 1、线程id
  • 2、上下文,包括各种寄存器的值、程序计数器和栈指针
  • 3、栈空间
  • 4、errno变量
  • 5、信号屏蔽字
  • 6、调度优先级
    这里写图片描述

6、线程的优点:

  • 1、创建⼀一个新线程的代价要⽐比创建⼀一个新进程⼩小得多
  • 2、 与进程之间的切换相⽐比,线程之间的切换需要操作系统做的工作要少很多
  • 3、线程占⽤用的资源要⽐比进程少很多
  • 4、能充分利⽤用多处理器的可并⾏行数量

  • 5、在等待慢速I/O操作结束的同时,程序可执⾏行其他的计算任务

  • 6、计算密集型应⽤用,为了能在多处理器系统上运⾏行,将计算分解到多个线程中实现
  • 7、 I/O密集型应⽤用,为了提⾼高性能,将I/O操作重叠。线程可以同时等待不同的I/O操作。

-线程的缺点:

1、性能损失
2、健壮性降低
3、缺乏访问控制
4、编程难度提高

二、线程的创建:

创建函数:
1、
功能:创建⼀一个新的线程 原型

  int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*star t_routine)(void*), void *arg);

参数

  • thread:返回线程ID
  • attr:设置线程的属性,attr为NULL表⽰示使⽤用默认属性
  • start_routine:是个函数地址,线程启动后要执⾏行的函数

  • arg:传给线程启动函数的参数 返回值:成功返回0;失败返回错误码

代码

  1 #include<stdio.h>
  2 #include<pthread.h>
  3 #include<unistd.h>
  4 void *thread_run(void * arg)
  5 {
  6          while(1){ printf("new thread,thread is :%lu,pid:%d\n",pthread_self(),getpid());
  7           sleep(1);
  8         //  return (void *) 1;                                                                                    
  9         }
 10 }
 11 int main()
 12 {
 13     pthread_t tid;
 14     pthread_create(&tid,NULL,thread_run,NULL);//1、取地址新的tid2、线程属性
 15     // 3、线程执行函数4、要传递给它的参数
 16     while(1)
 17     {
 18           printf("main thread,thread is :%lu,pid:%d\n",pthread_self(),getpid());
 19           sleep(1);
 20     }
 21   return 0;
 22 }     

程序运行结果:

这里写图片描述
查看进程和轻量级进程
这里写图片描述
解释
这里写图片描述

三、线程等待函数:

功能:等待线程结束 原型

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

参数

  • thread:线程ID

  • value_ptr:它指向⼀一个指针,后者指向线程的返回值 返回值:成功返回0;失败返回错误码

  1 #include<stdio.h>                                                                                                 
  2 #include<pthread.h>
  3 #include<unistd.h>
  4 void *thread_run(void * arg)
  5 {
  6          sleep(4);
  7          printf("new thread,thread is :%lu,pid:%d\n",pthread_self(),getpid());
  8          // sleep(1);
  9            return (void *) 123;
 10         
 11 }
 12 int main()
 13 {
 14     pthread_t tid;
 15     pthread_create(&tid,NULL,thread_run,NULL);//1、取地址新的tid2、线程属性
 16     // 3、线程执行函数4、要传递给它的参数
 17    // while(1)
 18    // {
 19    //       printf("main thread,thread is :%lu,pid:%d\n",pthread_self(),getpid());
 20    //       sleep(1);
 21    //}
 22    void *ret;
 23    pthread_join(tid,&ret);
 24    printf("join new thread success,ret:%d\n",(int)ret);
 25    return 0;
 26 }             

这里写图片描述

四、 线程终止函数

在线程的内部要慎重的调用exit,一旦调用exit,是进程终止而不是线程终止,要线程中止就要调用pthread_exit();

1、pthread_exit((void*)123);这种方式是线程终止
这里写图片描述
2、exit(123)这种方式是进程终止
这里写图片描述

五、线程取消函数

1、线程取消成功返回值为-1

pthread_cancel(tid);

这里写图片描述
2、线程还可以自己取消

pthread_cancel(pthread_self());

这里写图片描述
代码:

  1 #include<stdio.h>                                                                                                 
  2 #include<stdlib.h>
  3 #include<pthread.h>
  4 #include<unistd.h>
  5 void *thread_run(void * arg)
  6 {
  7          printf("new thread,thread is :%lu,pid:%d\n",pthread_self(),getpid());
  8           sleep(4);
  9           pthread_cancel(pthread_self());
 10          sleep(10);
 11          //  return (void *) 123;
 12         pthread_exit((void*)123);
 13         
 14 }
 15 int main()
 16 {
 17     pthread_t tid;
 18     pthread_create(&tid,NULL,thread_run,NULL);//1、取地址新的tid2、线程属性
 19     // 3、线程执行函数4、要传递给它的参数
 20     sleep(1);
 21     pthread_cancel(tid);
 22    // while(1)
 23    // {
 24    //       printf("main thread,thread is :%lu,pid:%d\n",pthread_self(),getpid());
 25    //       sleep(1);
 26    //}
 27    void *ret;
 28    pthread_join(tid,&ret);
 29    printf("join new thread success,ret:%d\n",(int)ret);
 30    return 0;
 31 }                                           
  • 3、从线程函数return。这种方法对主线程不适用,从main函数return相当于调用exit。

六、总结:

  • 1、如果thread线程通过return返回,value_ptr所指向的单元里存放的是thread线程函数的返回值。
  • 2、如果thread线程被别的线程调用用pthread_cancle异常终掉,value_ptr所指向的单元里存放的是常数PTHREAD_CANCELED。
  • 3、如果thread线程是自己调用pthread_exit终止的,value_ptr所指向的单元里存放的是传给pthread_exit的参数。如果对thread线程的终止状态不敢兴趣,可以传NULL给value_ptr参数。

这里写图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值