Java并发编程之美系列之线程基础

Java并发编程之美系列之线程基础

一、线程与Java线程

进程:进程是程序(指令的集合)的一次动态执行过程,是操作系统进行资源分配的基本单位。

线程:线程是进程的一个执行路径,一个进程可能不止一个线程(但最起码有一个主线程),线程间共享进程的资源,是操作系统进行任务调度的基本单位。

在Java中,当我们启动程序的main函数时其实就启动了一个JVM的进程,而main函数所在的线程就是这个进程的主线程。

image-20230924132239218

上图可以看出,一个进程有多个线程,多个线程共享进程的堆和方法区资源,但是每个线程有自己的程序计数器和栈区域。

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

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

  • 程序计数器:程序计数器是一块内存区域,用来记录线程当前要执行的字节码指令地址。其实程序计数器就是为了记录该线程让出CPU时的执行地址的,待再次分配到时间片时线程就可以从自己私有的计数器指定地址继续执行。另外需要注意的是,如果执行的是native方法,那么程序计数器记录的是undefined地址,只有执行的是Java代码时程序计数器记录的才是下一条字节码指令的地址。

  • 栈:每个线程都有自己的栈资源,用于存储该线程的局部变量,这些局部变量是该线程私有的,其他线程是访问不了的,除此之外栈还用来存放线程的调用栈帧

程序计数器是当前线程正在执行的字节码指令的地址。程序计数器是线程隔离的,每一个线程在工作的时候都有一个独立的计数器。编译后的字节码在没有经过JIT(即时编译器)编译前,是通过字节码解释器进行解释执行。其执行原理为:字节码解释器读取内存中的字节码,按照顺序读取字节码指令,读取一个指令就将其翻译成固定的操作,根据这些操作进行分支,循环,跳转等动作。

从字节码的执行原理来看,单线程的情况下程序计数器是可有可无的。因为即使没有程序计数器的情况下,程序会按照指令顺序执行下去,即使遇到了分支跳转这样的流程也会按照跳转到指定的指令处继续顺序执行下去,是完全能够保证执行顺序的。但是现实中程序往往是多线程协作完成任务的。JVM的多线程是通过CPU时间片轮转来实现的,某个线程在执行的过程中可能会因为时间片耗尽而挂起。当它再次获取时间片时,需要从挂起的地方继续执行。在JVM中,通过程序计数器来记录程序的字节码执行位置。