【日积月累】关于进程 线程和一些常见的多线程概念

时间:2023-01-21 00:00:31

      最近在看《深入解析Windows操作系统》和研究Java的JVM机制,觉得有些概念看起来简单,但是温故而知新,勤总结和归纳,对自己的知识体系的搭建大有裨益。此文引用了网上的一些博文和正在看的书中的一些段落。

 

【一】 进程和线程的一个形象的类比

pengpenglin的博文中 【原】多线程编程的基础知识点 中对进程和线程的关系作了一个很好的比喻:

 

下面我以一个日常生活中简单的例子来说明进程和线程之间的区别和联系:

【日积月累】关于进程 线程和一些常见的多线程概念
这副图是一个双向多车道的道路图,假如我们把整条道路看成是一个“进程”的话,那么图中由白色虚线分隔开来的各个车道就是进程中的各个“线程”了。

①这些线程(车道)共享了进程(道路)的公共资源(土地资源)。

②这些线程(车道)必须依赖于进程(道路),也就是说,线程不能脱离于进程而存在(就像离开了道路,车道也就没有意义了)。

③这些线程(车道)之间可以并发执行(各个车道你走你的,我走我的),也可以互相同步(某些车道在交通灯亮时禁止继续前行或转弯,必须等待其它车道的车辆通行完毕)。

④这些线程(车道)之间依靠代码逻辑(交通灯)来控制运行,一旦代码逻辑控制有误(死锁,多个线程同时竞争唯一资源),那么线程将陷入混乱,无序之中。

⑤这些线程(车道)之间谁先运行是未知的,只有在线程刚好被分配到CPU时间片(交通灯变化)的那一刻才能知道

 

 

【二】 什么是进程和线程?

在《深入解析Windows操作系统》第四版中提到:

"尽管表面上看起来程序和进程十分类似,但本质上它们却是截然不同的。程序 时指一个静态的指令序列 ,而进程 则是一个容器 ,其中包含了执行一个程序的特定实例时所用到得各种各样资源。"

 

 举个例子,一个Windows进程包含哪些元素呢?从最高层次的抽象来看:

  • 一个私有的虚拟地址空间 ,这是指该进程可以使用的一组虚拟内存地址
  • 一个可执行的程序,它定义了初始的代码和数据,并且被映射到该进程的虚拟地址空间中。
  • 一个已打开句柄的列表,这些句柄指向各种系统资源,比如信号量,通信端口和文件,该进程内所有线程都可以访问这些资源。
  • 一个被称为访问令牌 的安全环境,它标识了与该进程相关联的用户,安全组和特权。
  • 一个被称为进程ID 的唯一标识符。
  • 至少一个 执行线程。

 

    一个标准Windows 进程(32位)的内存分配结构如下图, 摘自《Windows Java Address Space 》:

【日积月累】关于进程 线程和一些常见的多线程概念

 

 

 

一个标准Java进程(32位)的内存分配结构如下图, 摘自《Windows Java Address Space 》:

【日积月累】关于进程 线程和一些常见的多线程概念

 

 

    一个完整Java进程分配的时候如下内容:

  1. Java VM
  2. Application byte code
  3. Native heap space
  4. Java heap space
  5. JIT'd code space
  6. Link Libraries

所以通过这个图我们就可以很清楚的明白,为啥你虽然有3.25G内存,减去2G os space,理论上一个java进程的Java Heap的Xmx可以设置成最大1.25G,但是实际上会报错:"Could not reserve enough space for object heap",原因就在于那剩下的1.25G不单单要被java heap瓜分,还要被Java VM进程的native heap,link libraries等等所占用。

 

 

【三】 (进程/线程)死锁 饥饿 饿死

 

死锁 :两个或两个以上进程等待对方释放资源。形成死锁最直观的现象就是出现等待环。

 

一个很形象的比喻:

两个山羊过一个独木桥都走到桥*,一个山羊等另一个山羊过去然后再过桥,另一个山羊等这个山羊过去才准备过去。结果两人都堵在中间无法动弹了。

 

饥饿:

 

饿死: