0%

请求分页管理方式

虚拟内存

定义:具有请求调入和置换功能,从逻辑上对内存容量加以扩充的一种存储器系统

虚拟内存的实现

  • 请求分页存储管理
  • 请求分段存储管理
  • 请求段页式存储管理

页表机制

  • 状态位P
  • 访问字段A
  • 修改位M
  • 外存地址

缺页中断机构

内中断(CPU内部)

  • 故障中断:错误条件引起可以被修复,如缺页中断

  • 陷入中断:有意为之,应用程序想调用内核功能。如系统调用

  • 终止中断:致命错误

外中断(CPU外部)

  • I/O中断请求
  • 人工干预

地址变换机构

  • 请求调页,判断是否在内存
  • 可能需要页面置换
  • 新增、修改页表项
  • 热点表项同步到快表

页面置换算法

最佳置换算法OPT

保障对低缺页率:每次选择淘汰最不可能再次被使用的页面 (无法实现)

最近最少页面置换算法LRU

保障时间和距离上的公平:每次选择淘汰最久最近未使用的页面 (需要硬件支持,开销大)

先进先出置换算法FIFO

保障顺序上的公平:每次选择淘汰最早进入内存的页面(Belady异常,性能差)

时钟置换算法

保障性能和开销均衡:为页面设置访问位(0/1),并链接形成循环队列,进程访问页面后置为1。发生缺页中断时,表针就扫描页面,位置为0就淘汰,位置为1就设置为0并向把表针向前移动一个位置。

最近未使用页面置换算法NRU:

额外考虑是否修改,保障最少I/O操作:设置访问位和修改位,访问位为优先原则。第一轮找(0,0) 第二轮找(0,1)并修改访问位为0,第三轮找(0,0),第四轮找(0,1)

页面分配策略

驻留集(驻留在主存中页面数)大小

  • 分配空间小,进程数量多,CPU时间利用效率就高

  • 进程在主存中页数少,错页率就高

  • 进程在主存中页数多,错页率并无明显改善

  • 全局页面置换算法:全局页面置换算法则是不考虑进程的个体情况,而是综合考虑整个系统内所有页面的情况。

  • 局部页面置换算法:局部页面置换算法是基于进程本身的页面访问模式的算法

固定分配局部置换:这种策略指定了每个进程在内存中占用固定数量的页面帧。当进程被加载到内存时,它会被分配一定数量的页面帧,并且在其执行期间,这些页面帧不会被其他进程使用。如果进程需要更多的内存空间,它必须等待其他进程释放内存,或者操作系统必须将某个进程的页面替换出去来为其腾出空间。这种策略可以简化内存管理,但可能导致内存浪费或资源不足的问题。

可变分配全局置换:这种策略允许进程的内存分配在运行时动态变化,而不是固定分配一定数量的页面帧。当进程需要更多内存时,操作系统可以为其分配更多页面帧,反之亦然。全局页面置换意味着页面替换决策基于整个系统的页面使用情况,不仅仅限于某个进程。这种策略可以更好地利用内存资源,但需要更复杂的管理算法来进行页面替换决策,以最大程度地提高系统性能。

可变分配局部置换:这种策略结合了前两种策略的特点。进程可以在运行时动态分配或释放内存,但页面替换决策仍然是基于进程本身的页面访问模式。这意味着每个进程可以根据需要调整内存分配,但页面替换决策仍然以进程为单位进行,以优化局部性。这种策略在某些情况下可以平衡内存使用效率和性能。

调入页面的时机

预调页策略

  • 一次性调入若干相邻页面
  • 多用于进程首次调入

请求调页

  • 运行时发现缺页时调入
  • I/O开销较大

从何处调页

外存分对换区和文件区,对换区可以保证地址是连续的,因此访问更快

系统拥有足够对换空间:

核心的放内存,辅助的放对换区

系统缺少足够对换空间:

不需要修改的一些文件比如函数计算公式不含数据,放入文件区。从内存调出时,不需要重新写入,直接覆盖就行,减少I/O操作。

优先把经常需要修改的文件放对换区,调出时的回写效率更高。

UNIX方式:

所有跟进程有关的文件,都放入文件区。 要换出都放入对换区

1.封装性

1.1 四种权限修饰符:private、缺省、protected、public

​ 类:只能用public、缺省修饰

​ 类的内部成员:四种都可以

1.2 作用:用四种权限修饰来修饰类和类的内部成员。当这些成员被调用时,体现可见性的大小

修饰符 本类内部 本包内 其他包的子类 其他包的非子类
private × × ×
缺省 × ×
protected ×
public

1.3 使用频率

比较高:public、private

低:缺省、protected

1.4 封装性体现

场景1:private类的属性,提供public的get和set方法,对此属性进行获取或修改

场景2:将类中不需要对外暴露的方法,设置为private

场景3:单例模式中构造器private的,避免在类的外部创建实例。

2.构造器

2.1 构造器的作用

作用1:搭配new关键字,创建类的对象

作用2:在创建对象的同时,可以给对象的相关属性赋值

2.2 构造器使用说明

  • 构造器声明的格式:权限修饰符 类名(形参){}

  • 创建类后,在没有显示提高任何构造器的情况下,系统默认提供一个空参的构造器,且构造器权限与类声明的权限相同

  • 一旦类中显示声明了构造器,则系统不再提供默认的空参构造器

  • 一个类中可以声明多个构造器,彼此之间构成重载

3.类中属性赋值过程

3.1类中属性赋值的渠道

  1. 默认初始化
  2. 显示初始化
  3. 构造器初始化
  4. 通过“对象.方法”的方式赋值;
  5. 通过“对象.属性”的方式赋值;

4.JavaBean

JavaBean:一种java语言写成的可重用组件

JavaBean符合如下标准的Java类:

  • 类是公共的
  • 有一个无参的公共的构造器
  • 有属性,且有对应的get、set方法

5.This 关键字

5.1 this可以调用的结构: 成员变量、方法、构造器

5.2 this的理解:当前对象(在方法中调用时)或当前正在创建的对象(在构造器中调用时)

5.3 this调用属性和方法

针对于方法内的使用情况(非static):

一般情况:通过对象a调用方法,可以在方法内调用当前对象a的属性或其他方法。此时,可以在属性和其他方法前使用“this.”,表示当前属性或方法所属的对象a。 但是通常,我们都选择省略”this.”结构

特殊情况: 如果方法的形参与对象的属性同名了,必须使用this进行区分。

5.4 this调用构造器

格式:this(形参)。

6.常见问题

6.1 java中内存结构的划分

  • java中内存结果划分为: 虚拟机栈、堆、方法区;程序计数器、本地方法栈
  • 虚拟机栈:以栈帧为基本单位,有入栈和出栈操作;每个栈帧入栈操作对应一个方法的执行;方法内的局部变量会存储在栈帧中。
  • 堆空间:new出来的结构(数组、对象): 1.数组,数组的元素在堆中 2.对象的成员变量在堆中
  • 方法区:加载的类的模版结构

6.2 Java引用类型有几种?

类、数组、接口;枚举、注解、记录

6.3 对象存在java内存的哪种区域里:

堆空间

6.4 main方法public能不能换成private?

能。但是改以后就不能作为程序的入口了,就只是一个普通的方法

6.5 构造方法和普通方法的区别

编写角度:没有共同点。 声明格式、作用都不同

字节码角度:构造器会以()方法的形态呈现,用以初始化对象。

6.6 成员变量和局部变量的区别:

  • 声明的位置
  • 内存中存放的位置
  • 作用域
  • 权限修饰符
  • 初始化值
  • 生命周期

6.7 变量赋值和构造方法加载的优先级问题

通过字节码文件可以发现变量显示赋值先于构造器中的赋值

对象在内存中的分配

  • 栈(Stack): 方法内定义的变量,存储在栈中

  • 堆(heap):new 出来的结构(比如:数组实体,对象的实体)。包括对象中的属性

  • 方法区(method area):存放类的模版

VwFAX.png

变量

成员变量:方法体外,类体内

局部变量:方法体内部等位置声明的变量

二者区分方式:

相同点:

  • 变量声明的格式相同:数据类型 变量名=变量值
  • 变量都有其有效的作用域:出了作用域就失效
  • 变量必须声明,后赋值,再使用

不同点

  • 类中声明的位置的不同:

    属性:声明在类内,方法外的变量

    局部变量:声明方法、构造器内部的变量

  • 在内存中分配的位置不同

    属性:随着对象的创建,存储在堆空间中

    局部变量:存储在栈空间中

    VwAsU.png

  • 生命周期

​ 属性:随着对象的创建而创建随着对象的消亡和消亡

​ 局部变量:随着方法对应的栈帧入栈,局部变量会在栈中分配;随着对应栈帧出栈,局部变量消亡

  • 作用域:

    属性:在整个类的内部都是有效

    局部变量:仅限于声明局部变量所在的方法(构造器、代码块)中

  • 权限修饰符进行修饰:

    权限修饰符:public、protected、缺省、Private(用于表名所修饰的结构可调用的范围的大小)

    属性:可以使用权限修饰符

    局部变量:不能使用任何权限修饰符

  • 默认值

    属性:都有默认初始化值

    局部变量:都没有默认初始化值

方法

语法:

​ 权限修饰符 返回值类型 方法名(形参列表)[throws 异常类型] {

​ // 方法体

}

方法调用的内存解析

形参:方法在声明时,一对()内声明的一个或多个形式参数

实参:方法在被调用时,实际传递给形参的变量或常量

对象数组:数组的元素可以是基本数据类型,也可以是引用数据类型。当元素是引用类型中的类时

VwHWt.png

方法的重载

定义:在同一个类中,允许在一个以上的同名方法,只要它们的参数列表不同即可。

编译器如何判断两个方法是相同的:

方法名相同,且形参列表相同。

​ 编译器先通过方法名确定了一波重载的方法,进而通过不同的形参列表,确定具体的方法

同一个类中不允许定义两个相同的方法

可变个数形参的方法

使用场景: 在调用方法时,可能出现方法形参的类型是确定的,但是参数的个数不确定。

语法: (参数类型 … 参数名)

说明:

  • 可变个数形参方法调用时,针对于可变的形参赋的实参个数可以为0,1,或多个
  • 可变个数形参的方法与同一个类中,同名的多个方法之间可以构成重载
  • 特例:可变个数形参的方法与同一个类中方法名相同,且与可变个数形参的类型相同的数组, 不构成重载. (因此可以把可变形参看成一个数组)
  • 可变个数形参必须声明在形参列表的最后

方法的值传递机制

方法内声明的局部变量来说,如果出现赋值操作

  • 基本数据类型变量: 将变量的数值传递出去
  • 引用数据类型变量: 将变量的地址值传递出去

方法的参数的传递机制:值传递机制

规则:实参给形参赋值的过程

  • 若形参是基本数据类型变量,则实参保存的数值赋给形参
  • 如果形参是引用数据类型变量,则将实参保存的地址赋给形参。

递归方法

递归分类:

  • 直接递归:方法自身调用自己
  • 间接递归:A方法调用B方法,B方法调用C方法,C方法调用A方法

注意:

  • 递归调用会占用大量的系统堆栈,内存耗用多,在递归调用层次多时速度要比循环慢得多

  • 在要求高性能的情况下尽量避免使用递归,递归既花时间又耗内存。考虑使用循环迭代

关键字:package、import

package说明

  • 一个源文件只有一个声明包的package语句

  • 包名,属于标识符,满足标识符命名规则和规范(全部小写)

    • 包通常使用所在公司的域名的倒置
  • 包对应于文件系统的目录,package语句中用”.”来指明包的层次。

  • 同一个包下可以声明多个结构(类、接口),但不能定义同名的结构。

包的作用

  • 包可以包含类和子包,划分项目层次便于管理
  • 帮助管理大型软件系统:将功能相近的类划分到同一个包中
  • 解决类命名冲突的问题
  • 控制访问权限

import

注意事项:

  • 如果使用’a.*’导入结构,表示可以导入a包下的所有结构如java.util.
  • 如果导入的类或接口是java.lang包下或者是当前包下的,则可以省略import语句
  • 如果已经导入java.a包下的类,那么如需要使用a包的子包下的类的话,仍然需要导入
  • 在代码中使用不同包下的同名的类,需要使用类的全类名的方式指明调用的是哪个类

死锁基本概念

定义:多个进程由于竞争资源而造成阻塞现象,若无外力作用,这些进程将无法继续前进
相似概念:饥饿: 等待时间过长以至于给进程推进和响应带来明显影响,但”饿而不死”
死锁产生原因:1.系统资源的竞争 2. 推进顺序非法
产生的必要条件

互斥条件:共享资源排他性访问
不剥夺条件:访问时该共享资源不会被剥夺
请求并保持条件:保持当前资源时请求另一资源
循环等待条件:存在共享资源的循环等待链

死锁的预防

1.破坏互斥条件
- 将只能互斥访问的资源改为同时共享访问
- 将独占锁改为共享锁
- 不是所有资源都能改成共享的

2.破坏剥夺条件
- 请求新资源无法满足时必须释放已有资源
- 由os协助强制剥夺某进程的资源
- 实现复杂代价高,此操作过多可能导致原进程无法推进

3.破坏请求等待条件
- 3.1 进程开始时一次性申请所需要的所有资源:资源浪费,进程饥饿
- 3.2 阶段性请求和释放资源:

4.破坏循环等等
- 对所有资源进行排序,按序号请求资源,请求时先低后高,释放时先高后低
- 对资源的编号相对稳定,限制了新设备增加
- 进程使用资源的顺序可能与系统编号的顺序不同,限制了用户编程

死锁避免

核心:安全性算法
系统安全状态

安全状态不一定会出现死锁
不安全状态可能会出现死锁

银行家算法

系统预判进程是否导致不安全状态
是则拒绝请求,否则答应请求

死锁检测

1.需要一种数据结构,保存相关资源请求和分配信息-资源分配图(G=(N,E))
2.需要一种算法,利用这些信息检测是否形成死锁-死锁定理(死锁状态充分条件)

资源分配图

两种资源
两种节点

死锁定理

当且仅当此状态下资源分配图是不可完全简化的
简化的过程类似于拓扑排序算法

死锁解除

1.资源剥夺

挂起死锁进程
剥夺其资源
将资源分配给其他(死锁)进程

2.撤销进程
3.进程回退

回退到避免死锁的地点
需要记录进程历史信息,设置回退点