美文网首页IT狗工作室C语言C语言&嵌入式
第3篇 Linux多线程--线程生命周期与状态

第3篇 Linux多线程--线程生命周期与状态

作者: 铁甲万能狗 | 来源:发表于2019-12-31 20:12 被阅读0次

在上一篇中,我们已经通过知道如何创建多个线程,本篇会谈论到线程的生命周期,在此之前应该了解一下线程在一个进程中的内存布局

主线程和线程栈

每个栈都是一个独立的虚拟内存分配,可以将其放置在任意位置。重要的是要注意,栈的大小通常是有限的。操作系统保留一定的最大的尺寸例如1MB或8MB)。栈不能超过该大小。但是当固定空间用完时,将触发栈溢出。在实践中这不是问题。实际上,超过合理的栈尺寸被认为是一个错误。而由多个段组成。只需添加更多细分即可任意增长。堆由用户模式的C库管理。内核对此一无所知。内核所做的只是在任意的位置提供虚拟内存。

什么是虚拟内存(Virtual Memory),这是涉及到系统内核的内存管理方式足以用一个系列的文章去讲解,以后有机会再说,或者你可以参考相关的文章。

线程栈只是进程所占据的虚拟内存中的一个连续块。 它的最大大小是固定的。 可能看起来像下面的图:


进程中的线程栈布局

我们知道,任何C/C++程序运行时,首先运行main函数,在多线程编程中,这个main函数也被称作初始线程主线程.

  • 1)主线程可以通过pthread_create系统调用创建子线程。
  • 2)主线程和其他子线程获取在整个CPU时钟周期中获得资源调度是均等的,也就是说所有线程默认状态下是异步独立运行的。
  • 3)主线程的确定了所有子线程的生命周期,一但主线程返回或者终止,其他子线程也会终止。
  • 4)主线程接受参数得的方式是通过argc和argv,而普通的线程只有一个参数void*类型的指针
  • 5)一般来说,主线程默认在栈中可以达到足够的长度,而普通的线程栈的是受到限制的。
  • 6)主线程伴随着进程的创建而创建.

线程的生命周期

下面是一个示例,我们在主线程函数暂停5秒,在创建的子线程函数中,我们暂停2秒,目地是检验上面线程的特征的第2点和第3点。

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include<string.h>

typedef struct{
    int age;
    char name[15];
} Person;


void *say_hello(void* per){
    sleep(2);
    Person* p=(Person*)per;
    printf("Hi!我的名字叫%s,今年%d岁\n",p->name,p->age);
    return (void*)0;
}
int main(int argc,char* argv){
      pthread_t tid;
      int err;

      Person s;
      memcpy(s.name,"Peter",15);
      s.age=25;
      err=pthread_create(&tid,NULL,say_hello,(void*)(&s));
      if(err!=0){
            printf("创建线程失败\n");
            return 0;
      }

      printf("主线程运行中!!\n");
      sleep(5);
      return 0;
}

Ok,我们的主线程先于子线程打印字符串,而字符串在调用pthread_create就已经运行,但它被延迟2秒才输出。这样就证明所有线程是独立运行的。


Peek 2019-12-31 14-03.gif

如果你我们修改一下上面的实例代码,将main函数中的sleep(5)注释,我们能够看到,子线程没有完全执行之前,主线程已经退出了,从而也强迫子线程跟随终止。

但有时我们的确没必要让主线程等待子线程执行完成后才退出的。使用pthread_exit系统调用可以做到主线程自己执行完后自己退出了(注意:进程没有退出),而子线程仍然可以独立运行直到其退出。

int main(int argc,char* argv){
      pthread_t tid;
      int err;

      Person s;
      memcpy(s.name,"Peter",15);
      s.age=25;
      err=pthread_create(&tid,NULL,say_hello,(void*)(&s));
      if(err!=0){
            printf("创建线程失败\n");
            return 0;
      }

      printf("主线程运行中!!\n");
      int *retval;
      pthread_exit(retval);

线程状态

我们会继续探讨一下线程在运行时的四种状态。

  • 准备等待可用的CPU资源,其他条件一切准备好。当线程被pthread_create创建时或者阻塞状态结束后就处于准备状态。
  • 运行 :线程已经获得CPU的使用权,并且正在运行,在多核心的机器中同时存在多个线程正在运行。如果这种情况不加以控制,会造成整个程序没响应。
  • 阻塞:指一个线程在执行过程中暂停,以等待某个条件的触发。
    • 例如线程可能在处理有关I/O的任务,可能I/O设备繁忙尚未响应或没有可用的I/O缓存。
    • 也可能当前线程等待一个可用的条件便来变量。
    • 错误地对一个已被锁住的互斥量加锁
    • 调用sigwait等待尚未发生的信号。
  • 终止:线程已经从回调函数中返回,或者调用pthread_exit返回,或者被强制终止。
    线程运行时的状态切换

小结

我们本篇讨论了主线程和子线程的关系,下一篇我们会讨论线程在运行时的状态。

相关文章

  • 线程的学习总结

    我打算从线程得生命周期开始总结多线程: 线程的生命周期: 新建状态:线程对象创建之后,线程进入新建状态. 就绪状态...

  • OC多线程

    iOS多线程方案 技术方案简介语言线程生命周期使用频率pthread通用多线程API 适用于unix/linux/...

  • Java知识梳理六

    一、Java多线程一 1.谈谈线程的生命周期和状态转移 关于线程生命周期的不同状态,在Java 5以后,线程...

  • 多线程

    常用的多线程 技术方案简介语言线程生命周期使用频率pthread一套通用的多线程API,适用于Unix\Linux...

  • 第3篇 Linux多线程--线程生命周期与状态

    在上一篇中,我们已经通过知道如何创建多个线程,本篇会谈论到线程的生命周期,在此之前应该了解一下线程在一个进程中的内...

  • 多线程知识点整理

    1、多线程基础 线程的生命周期(状态)NEW:就绪状态Java线程刚刚被创建,调用start()方法之后不代表线程...

  • 多线程编程

    多线程编程之Linux环境下的多线程(一)多线程编程之Linux环境下的多线程(二)多线程编程之Linux环境下的...

  • JAVA基础—创建线程的3种方式

    线程的生命周期(五种状态) 创建线程的三种方式对比 1. 创建多线程-继承Thread 运行结果 2. 创建多线程...

  • Java多线程模型

    Java多线程模型 生命周期 Java 线程的生命周期包括创建,就绪,运行,阻塞,死亡 5 个状态。一个 Java...

  • Java多线程

    1. 多线程 新建状态: 一个新产生的线程从新状态开始了它的生命周期。它保持这个状态直到程序 start 这个线程...

网友评论

    本文标题:第3篇 Linux多线程--线程生命周期与状态

    本文链接:https://www.haomeiwen.com/subject/nvrboctx.html