Java并发编程:虚拟内存之LRU算法实现

321 阅读2分钟

src=http___i0.hdslb.com_bfs_article_807aa46619617caf3a3ea976300b575abae0676c.png&refer=http___i0.hdslb.webp 本文已参与「新人创作礼」活动,一起开启掘金创作之路。

一、前言

       通过《Java并发编程:虚拟内存之页面置换》,我们已经了解了页面置换的过程以及几种常见的内存淘汰策略。在这几种策略中,Linux使用的是LRU算法(即最近最少使用算法),本文就给大家讲解下其实现逻辑。

二、LRU的关键数据结构

       在Linux中,为了实现LRU算法,它在每个内存区中都维护了两个链表,分别是active_list(活跃链表)和inactive_list(非活跃链表)。
       active_list用来记录内存区中经常访问的内存页,而inactive_list用来记录不经常访问的内存页。页面淘汰的时候,会从非inactive_list中选取。如下图。
list.webp

       除此之外,Linux还为链表中的每个内存页都设置了一个PG_referenced的标志位,作为内存页的访问标识

三、内存页申请流程

       Linux在申请一个新的内存页时,会将其放置到active_list的头部,并将其PG_referenced置为0。

四、内存页访问流程

       在应用程序访问内存页时,根据内存页的不同情况,LRU会进行不同的处理:
              1. 当该内存页在inactive_list中,且PG_referenced为0时,Linux会将该内存页的PG_referenced置为1;
              2. 当该内存页在inactive_list中,且PG_referenced为1时,Linux会将该内存页从inactive_list迁移到active_list中,并将其PG_referenced置为0;
              3. 当该内存页在active_list中,Linux会将该内存页的PG_referenced置为1。

五、内存页衰退流程

       若一个内存页在Linux中长时间没有应用程序访问时,会触发Linux的内存页衰退过程。过程与第4节相反,具体如下:
              1. 当该内存页在active_list中,且PG_referenced为1时,Linux会将该内存页的PG_referenced置为0;
              2. 当该内存页在active_list中,且PG_referenced为0时,Linux会将该内存页从active_list迁移到inactive_list中,并将其PG_referenced置为0;
              3. 当该内存页在inactive_list中,Linux会将该内存页的PG_referenced置为0。
       完整的内存页访问和衰退流程,可参考下图: 2222.webp

六、页面淘汰处理

       在进行页面淘汰时,Linux会从inactive_list的尾部开始,逐个遍历内存页,若该内存页的PG_referenced为1,则跳过,并将PG_referenced置为0,直到Linux找到一个PG_referenced为0的内存页。

七、后言

       既然看到这里了,感觉有所收获的朋友,不妨来个大大的点赞吧~~~