• 线程与进程基础


    线程与进程基础

    什么是进程

    • 是指计算机中已经运行的程序。
    • 曾是分时系统的基本运作单位。
    • 面向进程设计的系统中,进程是程序的基本执行实体。
    • 面向线程设计的系统中,进程不是基本运行的单位,而是线程的容器。
    • 程序本身只包含指令、数据及其组织结构的描述,进程才是程序的真正运行实例。(这点和Docker image 和 Docker container的关系很像)

    进程有五种状态:

    • 新生: 进程产生中(主动)
    • 运行: 正在运行中(被动)
    • 等待: 等待某事发生,比如等待用户输入完成。也称为阻塞。(主动)
    • 就绪: 进入CPU的等待队列,等待获取CPU(主动)
    • 结束: 完成运行(主动/被动)

    进程之间的各个状态是不能随便切换的。
    比如无法从等待直接转为运行,因为运行是指CPU目前正在执行,等待结束之后,只能进入CPU的等待队列,等待CPU的调度,然后等CPU去激活

    什么是线程

    • 线程是操作系统能够进行运算的最小单位。
    • 大部分情况下他被包含在进程之中,是进程的实际运作单位。
    • 一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程执行不同的任务。
    • 在unix 系统中,也被成为轻量级进程,但轻量级进程更多的是指内核线程,而把用户线程成为线程。

    线程有四种基本状态:

    • 产生
    • 阻塞
    • 非阻塞
    • 结束

    线程和进程的区别与联系

    • 一个进程可以有很多线程,每条线程并行执行不同的任务。
    • 同一个进程中的多条线程将共享该进程中的全部系统资源,比如:虚拟地址空间,文件描述符,信号处理等。
    • 同一个进程中的多个线程有各自的调用栈,自己的寄存器环境,自己的线程本地存储。

    操作系统在分配资源时要把资源分配给进程,但是CPU比较特殊,它是被分配到线程的,因为CPU真正执行的是线程,也就是说线程是CPU分配的基本单位。

    每个线程都有自己的栈资源,用于存储该线程的局部变量和线程的调用栈帧,这个局部变量是线程私有的,其他线程访问不到。

    堆是进程内最大的一块内存,堆是被进程中的所有线程共享的,是进程创建时分配的,堆里面主要放的是使用new操作创建的对象实例。

    方法区则用来存放JVM加载的类、常量、静态变量等信息,也是线程共享的。

    Java线程创建与运行

    三种方式:

    1. 继承Thread类,重写run方法(创建线程和线程的任务耦合)
    2. 实现Runnable接口重写run方法(线程任务和创建线程解耦,不能有返回值)
    3. 实现Callable<> 接口重写call<>方法(优点同上,可以有返回值)

    线程的等待与通知

    wait()函数

    当一个线程调用共享变量wait方法时,该调用线程会被挂起,知道发生一下事情才会返回:

    • 其他线程调用该共享对象的notify/notifyAll方法
    • 其他线程调用了该线程的interrupt方法,该线程抛出InterruptedException异常返回

    notify 函数

    一个线程调用共享对象的notify方法后,会唤醒一个在该共享变量上调用等待wait系列方法后挂起的一个随机线程

    注意:

    • 被唤醒的线程不能马上从wait方法返回继续执行,他必须获得了共享对象监视锁之后才能返回。
    • 只有获取了共享对象监视器锁之后才能够调用notify方法,否则会抛出IllegalMonitorStateException异常。

    notifyAll 函数

    通知所有等待在该共享变量上的wait线程。

    注意:

    • notifyAll 只会唤醒调用这个方法前调用了wait方法系列线程。

    Join 函数

    等待当前线程执行完成,之后执行其他事情。

    sleep

    当一个执行中的线程调用了sleep方法后,调用线程会暂时让指定时间的执行权,也就是这期间不参与CPU的调度,但是该线程拥有的资源监视器,比如锁,还是持有不让出的。

    执行之后正常返回,线程处于就绪状态,参与CPU调度。

    yield 方法

    当一个线程调用yield方法的时候,实际上就是在暗示线程调度器当前线程请求让出自己的CPU使用,但是线程调度器可以无条件忽略掉这个暗示。
    操作系统是以时间片为每个线程分配CPU的,正常情况下一个线程用完自己的时间片后,线程调度器才会进行下一轮的线程调度。
    而当一个线程调用Thread类的静态方法yield时,是在告诉线程调度器自己占有时间片没有用完但是自己不想用了,可以开启下一轮调度了。

    线程死锁

    定义

    死锁是指两个或者两个以上线程在执行过程中,因争夺资源而互相等待的现象,在无外力作用的情况下,这些线程会一直互相等待而无法继续进行下去。

    死锁产生的四个必要条件

    • 互斥条件
    • 请求并持有
    • 不可剥夺
    • 环路等待

    解除死锁:

    破坏掉上述四个条件中的一个即可。

  • 相关阅读:
    工厂模式之数据工厂
    面向过程的命令模式
    DLL共享主窗口的ADOCONNECTION
    插件框架
    人生哲理
    字符串函数大全
    汉化DBNavigator
    类继承复用之适配器模式
    Bootstraptagsinput标系统使用心得
    bootstrapdatepicker使用
  • 原文地址:https://www.cnblogs.com/qulianqing/p/13499065.html
Copyright © 2020-2023  润新知