一、操作系统中什么是线程和进程
线程和进程都是操作系统中定义的结构,进程是系统中一个独立的活动程序,比如像QQ、网易云音乐,进程是操作系统进行资源分配的基本单位,一个进程中的所有线程共享进程内的资源,而线程则是进程中真正执行程序的工作单位,一个进程中由于多子任务需要可能有多个线程,每个线程都是系统运行过程中的一个独立的指令执行流,主要是基于多任务并行处理的需要设计实现的,是操作系统进行CPU调度的基本单位,由操作系统根据调度算法对系统内所有线程进行调度轮流占用CPU执行程序,这称为并发执行,基于此我们才能在宏观上看到计算机上多个程序像是在同时运行一样。
二、Linux中的进程与线程
而在Linux系统中,上述“线程”概念是通过轻量级进程实现的,实现结构为task_struct,“进程”概念是由多个线程构成的一个线程组实现的。一个线程组中有一个“主线程”(事实上和线程组中其它线程是平级的),只有主线程在创建时会实际分配资源,其他线程通过浅拷贝共享主线程的资源,通过这样的方式实现的“进程是资源分配的基本单位”。
此外,Linux系统中还有进程组的概念,一个进程组由多个进程构成,其中有一个为主进程(父进程),进程组下的其他进程都是父进程的子进程。因此,整体结构如下:
- Linux系统中存在多个进程组
- 一个进程组下有多个进程(1:n)
- 一个进程对应一个线程组(1:1)
- 一个线程组下有多个线程(1:n)
内核层面:在每一个task_struct中,用命名空间中一个唯一的pid标识其自身,使用tgid(thread group id,等于线程组中主线程的pid)标识其所属的线程组,使用pgid(Process Group ID,等于其所属进程的父进程的tgid)标识其所属的进程组。
tgid相同的所有线程(轻量级进程)组成了概念上的“进程”。在Linux内核态中,只有task_struct,不区分进程和线程。
用户层面:我们在Linux系统中使用各种命令查看线程时还会显示“线程号”tid和父进程号ppid,那么实际上tid就是pid,ppid就等于pgid。而当打印PID时,通常实际上指的是tgid,用户层面称为“进程号”。
例如我们在使用top命令时,会打印系统当前运行的进程列表信息,其中的进程号PID指的就是进程的tgid
使用命令 <top -Hp 指定进程id> 显示的列表中的PID才是进程中线程的id
可能感觉有点绕,这样设计主要是为了让用户在使用Linux系统时有抽象的进程和线程的感觉,符合操作系统的抽象设计。我们只要在作为用户使用Linux时记住TID就是线程号,PID一般就是进程号,PPID就是父进程号,在实际分析Linux时不要搞错了就行了。
参考文章:
1.通俗易懂的了解——Linux线程模型和线程切换
2.进程各种id:pid、pgid、sid、全局pid、局部pid
3.Linux中pid与tid的异同及top中pid字段含义
三、Java中的线程
一个JVM就是一个进程。
Java中的线程是由Java虚拟机(JVM)管理的,是一个轻量级的执行单元。Java程序员可以使用Java的线程API来创建和控制线程,但实际上,这些线程最终都是由操作系统中的线程来执行的。
在Hotspot JVM中,每个线程与操作系统中的线程直接映射。当一个Java线程准备好执行后,此时操作系统的一个本地线程也同时创建,本地线程初始化完成后就开始执行Java线程run方法的字节码指令流译出的机器指令流,由系统进行调度。Java线程执行终止后,本地线程也会回收。
因此,Java中的线程可以看作是对操作系统线程的封装,它提供了一种方便的方式来管理和控制线程。Java程序员可以使用Java线程API来创建和启动线程,设置线程的优先级、状态等属性,并使用同步机制来协调多个线程之间的执行顺序。而操作系统负责管理线程的调度、内存分配等底层细节,以确保线程能够高效地运行。