"Java多线程基础-2:简介虚拟地址空间——保障进程间独立性的机制 "

简介: 如何保障进程之间这样的独立性?操作系统采用了“虚拟地址空间”的方式。

我们知道,进程之间是相互独立的,在操作系统级别中,一个进程所执行的程序无法直接访问另一个进程所执行的内存区域(即实现进程间通信比较困难);一个进程运行的失败也不会影响其它进程的运行。这使我们的操作系统功能更加稳定。


如何保障进程之间这样的独立性?操作系统采用了“虚拟地址空间”的方式。


一、每个进程都直接访问物理内存的地址会怎样?

物理内存是一块内存条




内存条上有许多内存颗粒(黑色块状的东西就是内存颗粒),它是内存条最核心的部件,是内存的储存介质。里面有许多的存储单元,类似于“小房间”。每个“小房间”都有编号,即“内存地址”。这时我们假设现在有两个进程,它们分别使用一定的内存资源:



此时,就出现了一个严重的问题:由于进程1和进程2使用的是同一块物理内存,且彼此之间没有约束,那么当进程1代码出现bug(如数组下标越界、野指针等问题时),就可能把进程2内存里的内容也搞坏了。进程1的bug,就很有可能引起进程2也bug。试想你浏览器用着用着,QQ崩了;QQ用着用着,桌面崩了……两个进程之间能直接相互影响,这极大地影响了操作系统整体的稳定性。


因而,虚拟地址空间就是来解决这个麻烦问题的。


二、“虚拟内存空间”是如何解决上述问题的?


现在有进程1和进程2,我们给两个进程分别分配一块虚拟的内存空间。然后,操作系统中提供了一个专门的数据结构:页表,通过页表,实现虚拟地址与实际的物理地址之间的映射。如进程1的虚拟地址空间是 0x00 - 0xff,页表就会将这段虚拟地址空间映射到物理内存上的真实地址 0xaa00 - 0xaaff 。同样的,进程2被分配的虚拟地址也会在页表的映射下对应到真实的物理内存上。



此时,站在这两个进程的角度看,它们的代码中操作的内存地址就是 0x00 - 0xff 这一段。这里访问的内存虽然会被操作系统自动映射到真实的物理内存上,但是进程自身是感知不到实际的物理地址是啥的。如果这时,进程1代码bug (比如数组下标越界,野指针等),就没事了。


因为任何一个内存操作都需要通过页表来“翻译”一下地址。如果出现野指针0x2ff,拿着这个地址去页表上找,发现页表上就没有这个地址!那页表便无法翻译,同时也就无法真正修改物理内存。这样一来,也就不会对别的进程的内存数据造成干扰了。


页表最大的作用就是校验,方便知道当前的虚拟地址是否有效。这样,一个进程崩了,不会对别的进程产生影响;进程之间无法直接干预,操作系统的稳定性也就上来了。


三、简述进程间通信的实现


有的情况下,我们需要进程之间能进行交互,相互配合。


但正如上面提到的,如果每个进程可以直接访问物理内存也即进程间没有隔离性,也就不需要进程间通信。进程1直接把算好的结果写到进程2的内存里就行。


但进程之间是有隔离性的。所谓进程间通信,就是在进程间隔离性的前提下,找一个公共的区域,让两个进程借助这个区域来完成数据交换。


这就好像疫情期间封小区,外面的人进不来,小区里的人也出不去(隔离性)。这时,如果小区里的人要买菜,就让小区外头送菜的人把菜放在保安亭,然后自己也去保安亭拿菜。那此时,这个保安亭就是公共空间,它帮助我们小区里被隔离的人和小区外的人实现了“通信”。


这可以理解为,所谓“公共空间”,就是在进程隔离性的情况下,作出了一些小小的妥协。


操作系统提供的实现进程间通信的方式有很多种,如管道、消息队列、共享内存、信号等等。由于编程语言的特点,C++对这部分的研究会比Java更加细致。因为在Java圈子中,并不是很鼓励多进程编程。Java更多地使用文件和socket这两种方式来完成进程间的通信。


在多线程与多进程编程都能满足并发编程的需求的前提下,Java也更鼓励多线程编程。



相关文章
|
存储 Linux API
【Linux进程概念】—— 操作系统中的“生命体”,计算机里的“多线程”
在计算机系统的底层架构中,操作系统肩负着资源管理与任务调度的重任。当我们启动各类应用程序时,其背后复杂的运作机制便悄然展开。程序,作为静态的指令集合,如何在系统中实现动态执行?本文带你一探究竟!
【Linux进程概念】—— 操作系统中的“生命体”,计算机里的“多线程”
|
5月前
|
Java 测试技术 API
【JUC】(1)带你重新认识进程与线程!!让你深层次了解线程运行的睡眠与打断!!
JUC是什么?你可以说它就是研究Java方面的并发过程。本篇是JUC专栏的第一章!带你了解并行与并发、线程与程序、线程的启动与休眠、打断和等待!全是干货!快快快!
885 3
|
5月前
|
JSON 网络协议 安全
【Java】(10)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
290 1
|
5月前
|
JSON 网络协议 安全
【Java基础】(1)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
310 1
|
11月前
|
并行计算 Linux
Linux内核中的线程和进程实现详解
了解进程和线程如何工作,可以帮助我们更好地编写程序,充分利用多核CPU,实现并行计算,提高系统的响应速度和计算效能。记住,适当平衡进程和线程的使用,既要拥有独立空间的'兄弟',也需要在'家庭'中分享和并行的成员。对于这个世界,现在,你应该有一个全新的认识。
386 67
|
并行计算 安全 Java
Python GIL(全局解释器锁)机制对多线程性能影响的深度分析
在Python开发中,GIL(全局解释器锁)一直备受关注。本文基于CPython解释器,探讨GIL的技术本质及其对程序性能的影响。GIL确保同一时刻只有一个线程执行代码,以保护内存管理的安全性,但也限制了多线程并行计算的效率。文章分析了GIL的必要性、局限性,并介绍了多进程、异步编程等替代方案。尽管Python 3.13计划移除GIL,但该特性至少要到2028年才会默认禁用,因此理解GIL仍至关重要。
1147 16
Python GIL(全局解释器锁)机制对多线程性能影响的深度分析
|
Java Linux 调度
硬核揭秘:线程与进程的底层原理,面试高分必备!
嘿,大家好!我是小米,29岁的技术爱好者。今天来聊聊线程和进程的区别。进程是操作系统中运行的程序实例,有独立内存空间;线程是进程内的最小执行单元,共享内存。创建进程开销大但更安全,线程轻量高效但易引发数据竞争。面试时可强调:进程是资源分配单位,线程是CPU调度单位。根据不同场景选择合适的并发模型,如高并发用线程池。希望这篇文章能帮你更好地理解并回答面试中的相关问题,祝你早日拿下心仪的offer!
403 6
|
数据采集 Java 数据处理
Python实用技巧:轻松驾驭多线程与多进程,加速任务执行
在Python编程中,多线程和多进程是提升程序效率的关键工具。多线程适用于I/O密集型任务,如文件读写、网络请求;多进程则适合CPU密集型任务,如科学计算、图像处理。本文详细介绍这两种并发编程方式的基本用法及应用场景,并通过实例代码展示如何使用threading、multiprocessing模块及线程池、进程池来优化程序性能。结合实际案例,帮助读者掌握并发编程技巧,提高程序执行速度和资源利用率。
674 0
|
安全 Java Kotlin
Java多线程——synchronized、volatile 保障可见性
Java多线程中,`synchronized` 和 `volatile` 关键字用于保障可见性。`synchronized` 保证原子性、可见性和有序性,通过锁机制确保线程安全;`volatile` 仅保证可见性和有序性,不保证原子性。代码示例展示了如何使用 `synchronized` 和 `volatile` 解决主线程无法感知子线程修改共享变量的问题。总结:`volatile` 确保不同线程对共享变量操作的可见性,使一个线程修改后,其他线程能立即看到最新值。
349 7
|
调度 开发者
深入理解:进程与线程的本质差异
在操作系统和计算机编程领域,进程和线程是两个核心概念。它们在程序执行和资源管理中扮演着至关重要的角色。本文将深入探讨进程与线程的区别,并分析它们在现代软件开发中的应用和重要性。
567 5

热门文章

最新文章