zoukankan      html  css  js  c++  java
  • linux 之线程基础 (一)、 线程的基本概念

    1. 线程基本概念

    1.1 为什么需要引入线程?

    现代操作系统OS引入了多任务的概念,传统上多任务的实现是多进程完成的。支持多任务就涉及到进程的切换,也就意味着进程上下文的切换。

    如果我们进程有很多,多进程的频繁切换,每次上下文切换都要做这些事,还是很耗资源的,我们想用一种机制能减少进程切换带来的资源消耗,所以很多操作系统中都引入了轻量级的进程的概念。也称之为线程。

    注意:上下文切换,上下文的意思是,我们运行一个进程所需要的资源。那就有内存,快速缓存,PC指针等等。切换上下文就是替换原先的内容,从某中角度去看需要切换task_struct结构以及虚拟内存空间。

    1.2 什么是线程?

    线程(thread),被称为轻量级进程(Lightweight Process Lwp)是程序执行调度的最小单位。在传统的系统中,一个进程只包含有一个线程。但在现代操作系统中,允许一个进程里面可以同时运行多个线程,这类程序就被称为多线程程序。一个进程内的各个线程之间共享程序的内存空间以及其他的资源(如打开的文件和信号等)。

    Linux实现线程的机制非常特别,从内核角度来说并没有线程的概念,Linux将线程仅仅视作一个与其他进程共享某些资源的特殊进程。所以Linux并没有特别的数据结构来描述线程,依然沿用task_struct结构来描述线程。

    注意:

    • 进程和线程 的比喻:公司、部门、部门员工。一个公司有多个部门,一个部门有多个员工。一个公司相当于一个完整的系统,一个部门相当于系统中的一个进程,一个员工相当于一个线程。部门员工之间许多信息可以共享,但是不同部门之间的信息共享比较麻烦。
    • 内核没有准备专门的机制来描述线程,它用的还是进程的那一套东西。只不过多个线程共享同一个进程中的资源

    1.3 多线程设计的优点

    • 大大提高了任务切换的效率。
    • 避免了额外的TLB(页表缓冲器)& cache的刷新。

    1.4 总结线程与进程的异同点

    线程就理解为一个执行者,它没有资源(线程是CPU调度的最小单位)。进程概念上是资源的宿主(进程是资源分配的最小单位)。Linux上的理念是大家都是执行者,资源共享。

    1.4.1相同点

    • 比如都具有ID,一组寄存器,状态,优先级以及所要遵循的调度策略。
    • 每个进程都有一个进程控制块,线程也拥有一个线程控制块(在Linux内核,线程控制块与进程控制块用同一个结构体描述,即struct
      task_struct),这个控制块包含线程的一些属性信息,操作系统使用这些属性信息来描述线程。
    • 线程和子进程的创建者可以在线程和子进程上实行某些控制,比如,创建者可以取消、挂起、继续和修改线程和子进程的优先级。

    1.4.2 不同点

    • 每个进程都拥有自己的地址空间,但线程没有自己独立的地址空间,而是运行在一个进程里的所有线程共享该进程的整个虚拟地址空间。
    • 线程的上下文切换时间开销比进程上下文切换时间开销要小的多。
    • 线程的创建开销远远小于进程的创建。
    • 子进程拥有父进程的地址空间和数据段的拷贝,因此当子进程修改它的变量和数据时,它不会影响父进程中的数据,但线程可以直接访问它进程中的数据段。
    • 进程之间通讯必须使用进程间通讯机制,但线程可以与进程中的其他线程直接通讯。
    • 线程可以对同一进程中的其他线程实施大量控制,但进程只能对子进程实施控制。
    • 改变主线程的属性可能影响进程中其他的线程,但对父进程的修改不影响子进程。

    1.5 与线程相关的命令

    1.5.1 查看线程

    ps 命令,-L参数显示进程,并尽量显示其LWP(线程ID)和NLWP(线程的个数)。

    ps -eLF |  grep  ^syslog
    

    在这里插入图片描述
    在这里插入图片描述

    1.5.2 pstree命令

    查看进程和线程的树形结构关系:

    pstree -p | grep syslog
    

    在这里插入图片描述

    1.6 线程组概念

    • 线程组是进程的别称
    • 对于多线程的进程,我们称之为线程组。其中开天劈地的main函数我们称为主线程,也就是线程组的组长,主线程的线程id等于进程id。主线程中会调用相关接口创建子线程。

    注意:

    • getpid函数,本质取得是线程组id,所以无论是在主线程还是在子线程中调用getpid都是都是获取线程组id。

    1.7 NPTL库的特点

    多线程运用了第三方库,因此在编译时,要加-lpthread 。(New POSIX Thread Library,NPTL库)。(也就是说标准C库,以及系统库中都没有提供 线程的库,我们所使用的线程库是第三方库。)

    • 是早期Linux Threads的改进
    • 采用1:1的线程模型
    • 显著的提高了运行效率
    • 信号处理效率更高

    1.8 同一进程的不同线程的资源共享

    1.8.1 一个进程中的多个线程共享以下资源

    • 可执行的指令(代码段共享)
    • 静态数据(全局变量和静态变量)
    • 进程中打开的文件描述符
    • 信号处理函数
    • 当前工作目录
    • 用户ID
    • 用户组ID

    1.8.2 每个线程私有的资源如下

    • 线程ID (TID)
    • PC(程序计数器)和相关寄存器
    • 堆栈(栈区)
    • 局部变量
    • 返回地址
    • 错误号 (errno)
    • 信号掩码和优先级
    • 执行状态和属性
  • 相关阅读:
    Codeforces Round #311 (Div. 2)
    hdu5441 并查集+克鲁斯卡尔算法
    hdu5439 二分
    hdu5422 最大表示法+KMP
    hdu3374 最大最小表示法 +kmp
    hdu2609最小表示法
    hdu4870 高斯消元
    关于并发编程是使用synchronized,lock?
    关于项目中遇到的问题-- trycatch 手动回滚事务
    关于项目中遇到的问题-- 请求接收的参数发生改变情况
  • 原文地址:https://www.cnblogs.com/lasnitch/p/12764126.html
Copyright © 2011-2022 走看看