Linux线程

Linux线程

  • Linux线程的发展

    1991年1月发布的Linux2.2内核中,进程是通过系统调用fork创建的,新的进程是原来进程的子进程。在2.2x版本中,不存在真正意义上的线程。Linux中常用的线程Pthread实际是通过进程来模拟的,即LWP。Linux2.2仅默认允许4096个进程/线程同时运行。

    2001年1月发布的Linux2.4内核消除了这个限制,并且允许在系统运行中动态调整进程数上限。因此进程数只受制于物理内存的多少。

    2003年12月发布的Linux2.6内核,NPTL线程模型出现。线程框架的改变包含Linux线程空间中许多新的概念,包括线程组、线程各自的本地存储区、POSIX风格信号

  • 什么是Linux线程

    线程是在共享内存空间中并发的多道执行路径,是linux系统中的最小执行单元。

    • 线程的标识

      和进程一样,每个线程也都有属于自己的ID,称为TID,在进程内唯一。Linux系统的线程实现确保了每个TID在系统范围内唯一,并且当线程不复存在后,其线程ID可以被其它线程复用

    • 线程管理

      线程管理包括创建线程(pthread_create)、终止线程(pthread_exit\pthread_cancel)、连接已终止的线程(pthread_join)、分离线程(pthread_detach)

      在主线程中调用pthread_exit函数,那么只有主线程自己会被终止,而其它线程仍然会照常运行。此时父进程是僵尸进程,当其它线程退出后,僵尸进程被回收。

    • 线程调度

      线程的动态优先级是可以被调度器实时调整的,而与之对应的线程静态优先级则只能由应用程序指定,如果应用程序没有显示指定一个线程的静态优先级,那么它将被设定为0.调度器并不会改变线程的静态优先级,线程的动态优先级是调度器在其静态优先级的基础上调整得出的,它在线程的运行顺序上起到了关键作用。而线程的静态优先级则决定了线程单次在CPU上运行的最长时间,也就是调度器分配给它的时间片大小。

      所有等待CPU的线程按照动态优先级从高到低顺序排列。每一个CPU的运行队列中都包含两个优先级阵列:其中一个用于存放正在等待运行的线程(激活的优先级阵列);而另一个则用于存放已经运行过但还未完成的线程(过期的优先级阵列)。下一个运行的线程总是从激活的优先级阵列中选出。如果调度器发现某个线程已经占用了CPU很长时间(该时间只会小于或等于给予该线程的时间片),并且激活的优先级阵列中还有优先级与它相同的线程在等待运行,那么调度器就会让那个等待的线程在CPU上运行,而被换下的线程会被排入过期的优先级阵列。当激活的优先级阵列中没有待运行的线程时,调度器会把这两个优先级阵列的身份互换,即之前的激活的优先级阵列成为新的过期的优先级阵列

    • 线程和进程中文件描述符的影响

      一个线程拥有自己的线程栈,并以此存储自己的私有数据。一个进程中的代码段、数据段、堆、信号处理函数,以及当前进程所持有的文件描述符

  • 线程模型

    线程实现模型主要有3个,分别是:用户级线程模型、内核级线程模型和两级线程模型。它们之间最大的差异在于线程与内核调度实体(Kernel Scheduling Entity)

    查看当前系统线程模型: getconf GNU_LIBPTHREAD_VERSION

    • NPTL

      NPTL是一个内核级线程模型线程库,当使用pthread_create创建一个线程,在内核相应创建一个调度实体

      NPTL没有使用管理线程

  • 多线程下的编程经验

    • 同步
    • 过载保护:多线程场景处理任务,常用到队列,即多线程从任务队列中取出任务,然后并发处理。当任务量大,线程来不及处理,需要及时丢弃队列中的任务,以保证高吞吐和低延迟。
    • 公平调度:使得某个线程负载过高
    • 析构出core: 线程退出时析构出core的问题,一个线程释放了还在被使用的资源
  • Reference: