IT狗工作室C语言C语言&嵌入式

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

2019-12-31  本文已影响0人  铁甲万能狗

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

主线程和线程栈

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

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

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


进程中的线程栈布局

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

线程的生命周期

下面是一个示例,我们在主线程函数暂停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);

线程状态

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

小结

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

上一篇 下一篇

猜你喜欢

热点阅读