线程与进程基础

线程与进程基础

什么是进程

  • 是指计算机中已经运行的程序。
  • 曾是分时系统的基本运作单位。
  • 面向进程设计的系统中,进程是程序的基本执行实体。
  • 面向线程设计的系统中,进程不是基本运行的单位,而是线程的容器。
  • 程序本身只包含指令、数据及其组织结构的描述,进程才是程序的真正运行实例。(这点和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时,是在告诉线程调度器自己占有时间片没有用完但是自己不想用了,可以开启下一轮调度了。

线程死锁

定义

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

死锁产生的四个必要条件

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

解除死锁:

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

posted @ 2020-08-13 21:46  Bluto  阅读(118)  评论(0编辑  收藏  举报