LRU算法C语言实现

合集下载

操作系统c语言设计程序模拟内存的动态分区内存管理方法。内存分区使用分区(说明)

操作系统c语言设计程序模拟内存的动态分区内存管理方法。内存分区使用分区(说明)

操作系统c语言设计程序模拟内存的动态分区内存管理方法。

内存分区使用分区(说明)摘要:1.引言2.内存动态分区原理a.内存分区类型b.内存分区算法3.C语言实现内存动态分区管理a.内存分配函数b.内存释放函数c.内存管理函数4.内存动态分区管理的应用a.进程管理b.文件系统5.内存分区管理的优化a.算法改进b.硬件支持6.结论正文:【引言】内存管理是操作系统中的核心功能之一,它负责对系统内存进行有效分配、管理和回收。

在众多内存管理方法中,动态分区管理因其灵活性和高效性而得到了广泛应用。

本文将介绍操作系统中动态分区管理的原理,以及如何使用C语言实现这一管理方法。

【内存动态分区原理】内存动态分区管理主要包括两个方面:内存分区类型和内存分区算法。

a.内存分区类型内存分区通常分为两类:固定大小分区和不固定大小分区。

固定大小分区是指内存中被分配成固定大小的分区,适用于内存需求稳定的场景。

不固定大小分区则根据实际需求进行分配,更加灵活。

b.内存分区算法内存分区算法主要包括首次适应算法(FF)、最佳适应算法(BF)、最坏适应算法(WF)等。

首次适应算法简单、快速分配,但可能导致内存碎片;最佳适应算法尽量使用最小空间满足需求;最坏适应算法则优先使用大内存块,分割后空闲块仍较大。

【C语言实现内存动态分区管理】在C语言中,我们可以通过编写内存分配函数、内存释放函数和内存管理函数来实现内存动态分区管理。

a.内存分配函数内存分配函数负责根据用户请求分配内存。

可以根据内存分区类型和内存分区算法实现。

例如,首次适应算法可以遍历空闲内存块表,找到第一个满足需求的空闲块并进行分配。

b.内存释放函数内存释放函数负责回收不再使用的内存块,将其归还给空闲内存池。

释放内存时,需要确保该内存块之后的内存块不会被误用。

c.内存管理函数内存管理函数负责监控内存使用情况,如内存总量、空闲内存块数量等,以便在必要时进行内存扩容或压缩。

【内存动态分区管理的应用】内存动态分区管理在操作系统中有着广泛应用,如进程管理和文件系统等。

OPT、FIFO、LRU算法的实现

OPT、FIFO、LRU算法的实现

OPT、FIFO、LRU算法的实现⼀、实验⽬的1. 了解虚拟存储技术的特点,掌握虚拟存储请求页式存储管理中⼏种基本页⾯置换算法的基本思想和实现过程,并⽐较它们的效率。

2. 了解程序设计技术和内存泄露的原因⼆、实验内容模拟实现请求页式存储管理的⼏种基本页⾯置换算法最佳淘汰算法(OPT)先进先出的算法(FIFO)最近最久未使⽤算法(LRU)三、实验原理1. 虚拟存储系统UNIX中,为了提⾼内存利⽤率,提供了内外存进程对换机制;内存空间的分配和回收均以页为单位进⾏;⼀个进程只需将其⼀部分(段或页)调⼊内存便可运⾏;还⽀持请求调页的存储管理⽅式。

当进程在运⾏中需要访问某部分程序和数据时,发现其所在页⾯不在内存,就⽴即提出请求(向CPU发出缺中断),由系统将其所需页⾯调⼊内存。

这种页⾯调⼊⽅式叫请求调页。

为实现请求调页,核⼼配置了四种数据结构:页表、页框号、访问位、修改位、有效位、保护位等。

2. 页⾯置换算法当CPU接收到缺页中断信号,中断处理程序先保存现场,分析中断原因,转⼊缺页中断处理程序。

该程序通过查找页表,得到该页所在外存的物理块号。

如果此时内存未满,能容纳新页,则启动磁盘I/O将所缺之页调⼊内存,然后修改页表。

如果内存已满,则须按某种置换算法从内存中选出⼀页准备换出,是否重新写盘由页表的修改位决定,然后将缺页调⼊,修改页表。

利⽤修改后的页表,去形成所要访问数据的物理地址,再去访问内存数据。

整个页⾯的调⼊过程对⽤户是透明的。

最佳淘汰算法(OPT):选择永不使⽤或在未来最长时间内不再被访问的页⾯予以替换。

先进先出的算法(FIFO):选择在内存中驻留时间最久的页⾯予以替换。

最近最久未使⽤算法(LRU):选择过去最长时间未被访问的页⾯予以替换。

3. ⾸先⽤srand( )和rand( )函数定义和产⽣指令序列,然后将指令序列变换成相应的页地址流,并针对不同的算法计算出相应的命中率。

(1)通过随机数产⽣⼀个指令序列,共320条指令。

lru算法c语言实现

lru算法c语言实现

lru算法c语言实现以下是LRU(最近最少使用)算法的C语言实现示例:```c#include <stdio.h>#include <stdlib.h>#include <time.h>// 最大缓存大小#defineCache_MAX 10// 缓存结构体typedef struct {int key;int value;int time;}CacheNode;// 缓存数组cacheNode cache[Cache_MAX];// 当前使用的缓存大小int currentCacheSize;// 缓存命中函数int cacheHit(int key) {int i;for (i = 0; i < currentCacheSize; i++) {if (cache[i].key == key) {cache[i].time = time(NULL);return 1;}}return 0;}// 缓存淘汰函数int cacheMiss(int key) {int i, j;for (i = 0; i < currentCacheSize; i++) { if (cache[i].key == key) {// 页命中,更新时间戳cache[i].time = time(NULL);return 1;}}// 页未命中,淘汰最久未使用的页j = 0;for (i = 1; i < currentCacheSize; i++) { if (cache[i].time < cache[j].time) { j = i;}}cache[j].key = key;cache[j].time = time(NULL);currentCacheSize++;return 0;}int main() {int key, value;while (1) {printf("输入key:");scanf("%d", &key);value = rand() % 100;if (cacheHit(key)) {printf("命中,value:%d\n", value); } else {printf("未命中,value:%d\n", value); cacheMiss。

LRU算法C语言实现

LRU算法C语言实现

LRU算法C语言实现LRU(Least Recently Used)算法是一种常见的缓存替换算法,它根据数据最近被访问的时间进行缓存替换。

当缓存满时,LRU算法将替换最长时间未被访问的数据。

下面是使用C语言实现LRU算法的代码:```c#include <stdio.h>#include <stdlib.h>typedef struct nodeint key;int value;struct node *prev;struct node *next;} Node;typedef struct lru_cacheint capacity;int count;Node *head;Node *tail;Node **hashmap;} LRUCache;LRUCache *createCache(int capacity)LRUCache *cache = (LRUCache *)malloc(sizeof(LRUCache)); cache->capacity = capacity;cache->count = 0;cache->head = NULL;cache->tail = NULL;cache->hashmap = (Node **)malloc(sizeof(Node *) * capacity); // 初始化hashmap为NULLfor (int i = 0; i < capacity; i++)cache->hashmap[i] = NULL;}return cache;void addNodeToHead(LRUCache *cache, Node *node)//将节点添加到链表头部node->next = cache->head;node->prev = NULL;if (cache->head != NULL)cache->head->prev = node;}cache->head = node;if (cache->tail == NULL)cache->tail = node;}void removeNode(LRUCache *cache, Node *node) //移除节点if (node->prev != NULL)node->prev->next = node->next;} elsecache->head = node->next;}if (node->next != NULL)node->next->prev = node->prev;} elsecache->tail = node->prev;}void moveToHead(LRUCache *cache, Node *node)//将节点移动到链表头部removeNode(cache, node);addNodeToHead(cache, node);void removeTail(LRUCache *cache)//移除链表尾部的节点if (cache->tail != NULL)Node *node = cache->tail;cache->tail = node->prev;if (node->prev != NULL)node->prev->next = NULL;} elsecache->head = NULL;}free(node);}int get(LRUCache *cache, int key)//根据键值获取缓存值,并将节点移动到链表头部int hash = abs(key) % cache->capacity;Node *node = cache->hashmap[hash];while (node != NULL)if (node->key == key)moveToHead(cache, node);return node->value;}node = node->next;}//如果节点不存在,返回-1return -1;void put(LRUCache *cache, int key, int value)//添加或更新缓存键值对int hash = abs(key) % cache->capacity;Node *node = cache->hashmap[hash];//如果缓存中已存在该键值对,更新节点的值并移动到链表头部while (node != NULL)if (node->key == key)node->value = value;moveToHead(cache, node);return;}node = node->next;}// 如果缓存已满,移除链表尾部的节点,同时更新hashmap if (cache->count >= cache->capacity)int tailKey = cache->tail->key;removeTail(cache);cache->hashmap[abs(tailKey) % cache->capacity] = NULL; cache->count--;}// 创建新的节点,并添加到链表头部和hashmapNode *newNode = (Node *)malloc(sizeof(Node)); newNode->key = key;newNode->value = value;newNode->prev = NULL;newNode->next = NULL;addNodeToHead(cache, newNode);cache->hashmap[hash] = newNode;cache->count++;void destroyCache(LRUCache *cache)//销毁缓存Node *node = cache->head;while (node != NULL)Node *temp = node;node = node->next;free(temp);}free(cache->hashmap);free(cache);```上述代码中,我们定义了两个数据结构,`Node`表示缓存中的节点,`LRUCache`表示整个缓存。

页面调度算法(FIFO,LRU,OPT)

页面调度算法(FIFO,LRU,OPT)
else { for( int j = 1;j <= n;j++ )
if( CompareQueue( Q,page ) ) { t--;DeQueue(Q,e);EnQueue(Q,e);flag = 1;break; }
if( flag == 0 ) { DeQueue( Q,x );
flag = 0;
}
cout << "缺页中断数为:" << endl;
cout << "w = " << w << endl;
delete [] a;
}
main()
{
int m,n;
cout << "输入页面数:" << endl;
cin >> m;
LinkQueue Q;
int page, t = 0,flag = 0,x;
InitQueue( Q );
for( int i = 1;i <= m;i++ )
{
page = a[ i ];
t++;
if( t <= n ) { EnQueue( Q,page );
}
cout << endl;
VisitQueue( Q );
cout << ":";
}
flag = 0;
}
cout << "缺页中断数为:" << endl;
cout << "t= " << t << endl;

lru算法及例题讲解

lru算法及例题讲解

lru算法及例题讲解
摘要:
1.LRU算法简介
2.LRU算法原理
3.LRU算法应用
4.例题讲解
5.总结与拓展
正文:
一、LRU算法简介
最近最少使用(Least Recently Used,简称LRU)算法是一种缓存置换策略,用于决定在内存有限的情况下,如何淘汰已失效的缓存数据。

LRU算法基于一个假设:最近访问过的数据很可能会在不久的将来再次被访问。

因此,当内存有限且需要腾出空间时,优先淘汰最近访问过的数据。

二、LRU算法原理
LRU算法通过维护一个访问顺序来实现。

当一个数据被访问时,将其放入一个队列(或栈)中,并按照访问顺序进行排序。

当需要淘汰缓存时,从队尾(或栈顶)移除最近访问过的数据。

三、LRU算法应用
LRU算法广泛应用于计算机科学领域,如操作系统、浏览器缓存、数据库等领域。

通过使用LRU算法,可以有效提高缓存利用率,提高系统性能。

四、例题讲解
题目:一个含有n个元素的缓存,采用LRU算法进行缓存置换,求第k个访问的元素在缓存中的位置。

解题思路:
1.初始化一个长度为n的数组,表示每个元素在缓存中的位置。

2.模拟访问过程,每次访问一个元素,按照LRU算法进行置换,并记录访问顺序。

3.当访问第k个元素时,找到其在访问顺序中的位置,即为在缓存中的位置。

五、总结与拓展
LRU算法作为一种高效的缓存置换策略,在实际应用中具有重要意义。

了解LRU算法的原理和应用,可以帮助我们更好地解决实际问题。

LRU页面调度算法实现

LRU页面调度算法实现

LRU页面调度算法实现学院计算机科学与技术专业计算机科学与技术学号学生姓名指导教师姓名2014年3月16 日目录1.实验要求 (2)2.实验目的 (2)3.实验内容 (2)4.相关知识 (2)5.实验原理 (3)6.流程图 (4)7.源代码 (5)8.运行结果 (9)9.实验心得 (10)10.参考文献 (11)LRU页调度算法实现一实验要求:1.不同的功能使用不同的函数实现(模块化),对每个函数的功能和调用接口要注释清楚。

对程序其它部分也进行必要的注释。

2.对系统进行功能模块分析、画出总流程图和各模块流程图。

3.用户界面要求使用方便、简洁明了、美观大方、格式统一。

所有功能可以反复使用,最好使用菜单。

4.通过命令行相应选项能直接进入某个相应菜单选项的功能模块。

5.所有程序需调试通过。

二实验目的:将课本上的理论知识和实际有机的结合起来,独立分析和解决实际问题的机会。

进一步巩固和复习操作系统的基础知识。

培养学生结构化程序、模块化程序设计的方法和能力。

提高学生调试程序的技巧和软件设计的能力。

提高学生分析问题、解决问题以及综合利用C 语言进行程序设计的能力。

三实验内容:程序应模拟实现LRU 算法思想,对n个页面实现模拟调度。

四相关知识:1.虚拟存储器的引入:局部性原理:程序在执行时在一较短时间内仅限于某个部分;相应的,它所访问的存储空间也局限于某个区域,它主要表现在以下两个方面:时间局限性和空间局限性。

2.虚拟存储器的定义:虚拟存储器是只具有请求调入功能和置换功能,能从逻辑上对内存容量进行扩充的一种存储器系统。

3.虚拟存储器的实现方式:分页请求系统,它是在分页系统的基础上,增加了请求调页功能、页面置换功能所形成的页面形式虚拟存储系统。

请求分段系统,它是在分段系统的基础上,增加了请求调段及分段置换功能后,所形成的段式虚拟存储系统。

五.实验原理:目前有许多页面调度算法,本实验主要涉及最近最久未使用调度算法。

页面淘汰算法实验报告

页面淘汰算法实验报告

操作系统实验报告课题:页面淘汰算法专业:班级:学号:姓名:年月日目录一实验目的 (3)二实验要求 (3)三背景知识 (3)四总体设计 (4)五详细设计 (7)六运行结果分析 (9)七心得体会 (13)八参考文献 (14)附:源代码 (15)一、实验目的本实验主要对操作系统中请求分页式内存管理及其应用的一些关键算法进行模拟。

学生通过设计与实现Clock算法,能够加强对相应理论的理解,并对了解操作系统内部的基本处理原理与过程也有很多益处。

利用简单的数据结构,模拟实现操作系统中的页面置换机制,通过写程序模拟实现上述三种内存页面置换算法,使学生进一步掌握内存页面置换的方法。

对操作系统中内存的管理有一个实践上的认识。

1、用C语言编写OPT、FIFO、LRU三种置换算法。

2、熟悉内存分页管理策略。

3、了解页面置换的算法。

4、掌握一般常用的调度算法。

5、根据方案使算法得以模拟实现。

6、锻炼知识的运用能力和实践能力。

二、实验要求●设计随机页面序号产生程序,并说明随机的性能和其性能可能对算法的影响●编写页面淘汰算法(FIFO、OPT、LRU)●结果数据的显示或提取●结果数据的分析几点说明:●设计并绘制算法流程,附加说明所需的数据结构●如何标记时间的先后、最久的将来、最久未被使用●描述Clock算法的基本原理、必要的数据结构、算法执行流程图、编码实现。

1)初始化:输入作业可占用的总页框数,初始化置空。

2)输入请求序列:输入一个作业页号访问请求序列,依次占用相应页框,直至全部占用;3)Clock算法:当页框全部占用后,对于后续新的页号访问请求,执行Clock 算法,淘汰1个页面后装入新的页号。

4)显示当前分配淘汰序列:显示淘汰的页号序列。

三、背景知识:在操作系统当中,在进程运行过程中,若其访问的页面不在内存中而需把他们调入内存,但内存已无空闲空间时,为了保证该进程能够正常的运行,系统必须从内存中调出一页程序或数据送到磁盘的兑换区中,但是应该是哪个页面被调出,需根据一定的算法来确定。

操作系统页面调度算法程序实验报告

操作系统页面调度算法程序实验报告

操作系统页面调度算法程序实验报告一、实验背景操作系统是计算机系统中最重要的组成部分之一,它负责管理计算机的资源、协调各个程序的运行和提供用户与计算机之间的接口。

而页面调度算法则是操作系统中非常重要的一个部分,它主要用于管理内存中的页面,以提高计算机系统的性能和效率。

二、实验目的本次实验旨在通过编写一个页面调度算法程序,深入理解操作系统中页面调度算法的原理和实现方法,并掌握如何使用C语言进行程序设计和开发。

三、实验原理1. 页面调度算法概述在操作系统中,为了提高内存利用率和进程执行效率,通常会将进程所需的数据或指令分割成多个大小相等的块(即“页面”),并将这些页面存储到内存中。

当进程需要访问某个页面时,如果该页面已经在内存中,则直接访问即可;如果该页面不在内存中,则需要进行“缺页处理”,将其从磁盘读入内存,并将其中一个已经在内存中但未被访问过一段时间的页面替换出去。

而为了确定应该替换哪个页面,就需要使用一种称为“页面调度算法”的技术来进行决策。

常见的页面调度算法有FIFO、LRU、LFU等。

2. FIFO算法FIFO(First In First Out)算法是最简单的页面调度算法之一,它的原理是将最先进入内存的页面替换出去。

具体来说,当一个新页面需要进入内存时,如果内存已经满了,则将最先进入内存的页面替换出去,并将新页面插入到队列末尾。

3. LRU算法LRU(Least Recently Used)算法是一种比较常用的页面调度算法,它的原理是根据页面最近被访问的时间来进行决策。

具体来说,当一个新页面需要进入内存时,如果内存已经满了,则将最近访问时间最早且未被修改过的页面替换出去,并将新页面插入到队列末尾。

4. LFU算法LFU(Least Frequently Used)算法是一种根据页面使用频率来进行决策的调度算法。

具体来说,当一个新页面需要进入内存时,如果内存已经满了,则将使用频率最低的那个页面替换出去,并将新页面插入到队列末尾。

先进先出(FIFO)页面置换算法C语言实现、最近最久未使用(LRU)页面置换算法C语言实现

先进先出(FIFO)页面置换算法C语言实现、最近最久未使用(LRU)页面置换算法C语言实现

先进先出(FIFO)页⾯置换算法C语⾔实现、最近最久未使⽤(LRU)页⾯置换算法C语⾔实现1.实现效果2.实现源代码1 #include<iostream>2 #include<process.h>3 #include<stdlib.h>4 #include<ctime>5 #include<conio.h>6 #include<stdio.h>7 #include<string.h>8using namespace std;910#define Myprintf printf("|---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---|\n")/*表格控制*/11#define bsize 4 //物理块⼤⼩12#define psize 16 //进程⼤⼩13void chushihua();//初始化函数14void ymzh();16void changeaddr(struct Page p[], int logaddr);17void dizhizhuanhuan();18void menu();19int wang();2021int yemianliu[32]={0};//全局变量数组,地址流22int p;23struct Page {24int pno;//页号25int flag;//标志位26int cno;//主存号27int modf;//修改位28int addr;//外存地址29 }Page; //全局变量p是⼀共有多少地址流3031 typedef struct pagel32 {33int num; /*记录页⾯号*/34int time; /*记录调⼊内存时间*/35 }Pagel; /*页⾯逻辑结构,⽅便算法实现*/3637 Pagel b[bsize]; /*内存单元数*/38int c[bsize][psize];/*保存内存当前的状态:缓冲区*/39int queue[100];/*记录调⼊队列*/40int k;/*调⼊队列计数变量*/41int phb[bsize]={0};//物理块标号42int pro[psize]={0};//进程序列号43int flag[bsize]={0};//进程等待次数(存放最久未被使⽤的进程标志)*/ 44int i=0,j=0;//i表⽰进程序列号,j表⽰物理块号*/45int m =-1,n =-1;//物理块空闲和进程是否相同判断标志*/46int mmax=-1, maxflag=0;//标记替换物理块进程下标*/47int count =0; //统计页⾯缺页次数4849void chushihua() //初始化函数50 {51int t;52 srand(time(0));//随机产⽣指令序列53 p=12+rand()%32;54 cout<<"地址流序列:";55 cout<<endl;56for(i=0; i<p; i++)57 {58 t=1+rand()%9;59 yemianliu[i]=t;//将随机产⽣的指令数存⼊页⾯流60 }61for (i=p-1;i>=0;i--)62 {63 cout<<yemianliu[i]<<"";64 }65 cout<<endl;66 }67void ymzh()68 {69 chushihua();70 yemianzhihuan();71 }7273void yemianzhihuan()74 {75int a;76 printf("----------------------------------\n");77 printf("☆☆欢迎使⽤分页模拟实验系统☆☆\n");78 printf("----------------------------------");79 printf("☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆\n");80 printf("☆☆1.进⼊硬件地址变换算法☆☆\n");81 printf("☆☆------------------------☆☆\n");82 printf("☆☆2.进⼊页⾯置换算法☆☆\n");83 printf("☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆\n");84 printf("请输⼊您的选择:");85switch(a)86 {87case1:88 ymzh();89break;90case2:91 wang();92break;93default:94 cout<<"输⼊有误,请重新输⼊!"<<endl;95break;96 }97 }98100int j=logaddr/64;//对应的块号101int k=logaddr%64; //对应的偏移量102int flag=0;103int addr;104for(int i=0;i<8;i++)105 {106if(p[i].pno==j)//找到对应的页号107 {108if(p[i].flag==1)//页⾯标志为1109 {110 addr=p[i].cno*64+k;111 cout<<"物理地址为:"<<addr<<endl;112 cout<<"详细信息:"<<"\t页⾯号:"<<p[i].pno<<"\t 主存号:"<<p[i].cno<<"\t偏移量:"<<k<<endl; 113 flag=1;114break;115 }116 }117 }118119if(flag==0)120 cout<<"该页不在主存,产⽣缺页中断"<<endl;121 }122123void dizhizhuanhuan()124 {125int a;126int ins;//指令逻辑地址127struct Page p[8];128 p[0].pno=0;p[0].flag=1;p[0].cno=5;p[0].modf=1;p[0].addr=011;129 p[1].pno=1;p[1].flag=1;p[1].cno=8;p[1].modf=1;p[1].addr=012;130 p[2].pno=2;p[2].flag=1;p[2].cno=9;p[2].modf=0;p[2].addr=013;131 p[3].pno=3;p[3].flag=1;p[3].cno=10;p[3].modf=0;p[3].addr=015;132 p[4].pno=4;p[4].flag=0;p[4].addr=017;133 p[5].pno=5;p[5].flag=0;p[5].addr=025;134 p[6].pno=6;p[6].flag=0;p[6].addr=212;135 p[7].pno=7;p[7].flag=0;p[7].addr=213;136 printf("\t\t\t--------------------------------\n");137 printf("\t\t\t☆☆欢迎使⽤分页模拟实验系统☆☆\n");138 printf("\t\t\t---------------------------------\n");139 printf("\t\t\t☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆\n");140 printf("\t\t\t☆☆1.输⼊指令☆☆\n");141 printf("\t\t\t☆☆------------------------☆☆\n");142 printf("\t\t\t☆☆2.进⼊页⾯置换算法☆☆\n");143 printf("\t\t\t☆☆------------------------☆☆\n");144 printf("\t\t\t☆☆0.EXIT ☆☆\n");145 printf("\t\t\t☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆\n");146while(a!=0)147 {148 cout<<endl<<"请输⼊您的选择:";149 cin>>a;150151 cout<<"页号"<<"标记位"<<"外存地址"<<"主存号"<<endl;152for(int i=0;i<8;i++)153 {154 cout<<p[i].pno<<"\t"<<p[i].flag<<"\t"<<p[i].addr<<"\t";155if(p[i].flag)156 cout<<p[i].cno;157 cout<<endl;158 }159160switch(a)161 {162case0:printf("\t\t\t再见!\t\t\t\n"); break;163case1:164 cout<<"请输⼊指令的逻辑地址:";165 cin>>ins;166 changeaddr(p, ins);break;167case2: system("CLS"); a=wang();break;168default:cout<<"输⼊有误,请重新输⼊!"<<endl;break;169 }170 }171 }172173void menu()174 {175int a;176 printf("\t\t\t--------------------------------\n");177 printf("\t\t\t☆☆欢迎使⽤分页模拟实验系统☆☆\n");178 printf("\t\t\t---------------------------------\n");179 printf("\t\t\t☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆\n");180 printf("\t\t\t☆☆1.输⼊指令☆☆\n");181 printf("\t\t\t☆☆------------------------☆☆\n");182 printf("\t\t\t☆☆2.进⼊页⾯置换算法☆☆\n");184 printf("\t\t\t☆☆0.EXIT ☆☆\n");185 printf("\t\t\t☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆\n"); 186 printf("请选择所要执⾏的操作:");187 scanf("%d",&a);188switch(a)189 {190case0: printf("\t\t\t-再见!-\t\t\t\n");break;191case1: dizhizhuanhuan (); break;192case2: wang (); break;193default:cout<<"输⼊有误,请重新输⼊!"<<endl;break; 194 }195 }196int main()197 {198 menu();199 }200201//****************随机产⽣序列号函数202int* build()203 {204 printf("随机产⽣⼀个进程序列号为:\n");205int i=0;206for(i=0; i<psize; i++)207 {208 pro[i]=10*rand()/(RAND_MAX+1)+1;209 printf("%d ", pro[i]);210 }211 printf("\n");212return(pro);213 }214215//***************************************查找空闲物理块216int searchpb()217 {218for (j=0;j<bsize; j++)219 {220if(phb[j] == 0)221 {222 m=j;223return m;224break;225 }226 }227return -1;228 }229//************************************查找相同进程230int searchpro()231 {232for(j=0;j< bsize;j++)233 {234if(phb[j] =pro[i])235 {236 n=j;237return j;238 }239 }240return -1;241 }242243//*************************初始化内存244void empty()245 {246for(i=0;i<bsize;i++)247 phb[i]=0;248 count=0; //计数器置零249 } //******先进先出页⾯置换算法250void FIFO()251 {252for( i=0; i<psize; i++)253 {254// m=searchpb();255// n=searchpro();256//找到第⼀个空闲的物理快257for(j=0;j<bsize;j++) {258if(phb[j] == 0){259 m=j;260break;261 }262 }263//找与进程相同的标号264for(j=0;j<bsize;j++) {265if(phb[j] == pro[i]){266 n=j;268 }269270//找flag值最⼤的271for(j=0;j<bsize;j++)272 {273if(flag[j]>maxflag)274 {275 maxflag = flag[j];276 mmax = j;277 }278 }279280if(n == -1)//不存在相同进程281 {282if(m != -1)//存在空闲物理块283 {284 phb[m]=pro[i];//进程号填⼊该空闲物理块285// count++;286 flag[m]=0;287for (j=0;j<=m; j++)288 {289 flag[j]++;290 }291 m=-1;292 }293else//不存在空闲物理块294 {295 phb[mmax] =pro[i];296 flag[mmax] =0;297for (j=0;j<bsize;j++)298 {299 flag[j]++;300 }301 mmax = -1;302 maxflag = 0;303 count++;304 }305 }306else//存在相同的进程307 {308 phb[n] = pro[i];309for(j=0;j<bsize;j++)310 {311 flag[j]++;312 }313 n=-1;314 }315for(j=0;j < bsize;j++)316 {317 printf("%d ", phb[j]);318 }319 printf("\n");320 }321 printf("缺页次数为:%d\n",count);322 printf("缺页率 :%16. 6f",(float)count/psize);323 printf("\n");324 }325/*初始化内存单元、缓冲区*/326void Init(Pagel *b,int c[bsize][psize])327 {328int i,j;329for (i=0;i<psize;i++)330 {331 b[i].num=-1;332 b[i].time=psize-i-1;333 }334for(i=0;i<bsize;i++)335for(j=0;j<psize;j++)336 c[i][j]=-1;337 }338/*取得在内存中停留最久的页⾯,默认状态下为最早调⼊的页⾯*/ 339int GetMax(Pagel *b)340 {341int i;342int max=-1;343int tag=0;344for(i=0;i<bsize;i++)345 {346if(b[i].time>max)347 {348 max=b[i].time;349 tag= i;350 }353 }354355/*判断页⾯是否已在内存中*/356int Equation(int fold, Pagel *b)357 {358int i;359for(i=0;i<bsize;i++)360 {361if(fold==b[i]. num)362return i;363 }364return -1;365 }366/*LRU核⼼部分*/367void Lruu(int fold, Pagel *b)368 {369int i;370int val;371 val=Equation(fold, b);372if (val>=0)373 {374 b[val].time=0;375for(i=0;i<bsize;i++)376if (i!=val)377 b[i].time++;378 }379else380 {381 queue[++k]=fold;/*记录调⼊页⾯*/382 val=GetMax(b);383 b[val].num=fold;384 b[val].time=0;385for (i=0;i<bsize;i++){386387// URLcount++;388if (i!=val)389 b[i].time++;390 }391 }392 }393394void LRU()395 {396int i,j;397 k=0;398 Init(b, c);399for(i=0; i<psize; i++)400 {401 Lruu(pro[i],b);402 c[0][i]=pro[i];403/*记录当前的内存单元中的页⾯*/404for(j=0;j<bsize;j++)405 c[j][i]=b[j].num;406 }407408/*结果输出*/409 printf("内存状态为:\n");410 Myprintf;411for(j=0;j<psize;j++)412 printf("|%2d", pro[j]);413 printf("|\n");414 Myprintf;415416for(i=0;i<bsize;i++)417 {418for(j=0; j<psize; j++)419 {420if(c[i][j]==-1)421 printf("|%2c",32);422else423 printf("|%2d",c[i][j]);424 }425 printf("|\n");426 }427428 Myprintf;429// printf("\n调⼊队列为:");430// for(i=0;i<k;i++)431// printf("%3d", queue[i]);432433 printf("\n缺页次数为:%6d\n 缺页率 :%16. 6f", k+1,(float)(k+1)/psize); 434 }437int wang()438 {439int sel;440do{441 printf("\t\t\t--------------------------------\n");442 printf("\t\t\t☆☆欢迎使⽤分页模拟实验系统☆☆\n");443 printf("\t\t\t---------------------------------\n");444 printf("\t\t\t☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆\n");445 printf("\t\t\t☆☆虚拟内存☆☆\n");446 printf("\t\t\t☆☆------------------------☆☆\n");447 printf("\t\t\t☆☆1.产⽣随机序列☆☆\n");448 printf("\t\t\t☆☆------------------------☆☆\n");449 printf("\t\t\t☆☆2.最近最久未使⽤☆☆\n");450 printf("\t\t\t☆☆------------------------☆☆\n");451 printf("\t\t\t☆☆3.先进先出☆☆\n");452 printf("\t\t\t☆☆------------------------☆☆\n");453 printf("\t\t\t☆☆0.退出☆☆\n");454 printf("\t\t\t☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆\n");455 printf("请选择所要执⾏的操作:");456 scanf("%d",&sel);457switch(sel)458 {459case0: printf("\t\t\t再见!t\t\t\n"); break;460case1: build(); break;461case2: printf("最近最久未使⽤\n"); LRU();empty(); printf("\n");break; 462case3: printf("先进先出算法\n"); FIFO();empty();printf("\n");break; 463default:printf("请输⼊正确的选项号!");printf("\n\n");break;464 }465 }while(sel !=0 );466return sel;467 }。

lru页面置换算法实验c语言总结

lru页面置换算法实验c语言总结

LRU页面置换算法实验C语言总结1.引言在计算机科学中,页面置换算法是解决主存容量有限的情况下,如何有效地管理页面(或称为内存块)的一种重要方法。

L RU(L ea st Re ce nt ly Us e d)页面置换算法是其中一种经典的策略,通过淘汰最久未使用的页面来提高内存的利用率。

本文将总结使用C语言实现L RU页面置换算法的相关实验。

2.算法原理L R U页面置换算法的核心思想是:最近被访问的页面可能在未来继续被访问,而最久未被使用的页面可能在未来也不再被访问。

基于这一思想,L R U算法维护一个页面访问的时间顺序链表,每次发生页面置换时,选择链表头部(即最久未使用)的页面进行淘汰。

3.实验设计本次实验旨在使用C语言实现LR U页面置换算法,并通过模拟页面访问的过程来验证算法的正确性。

具体设计如下:3.1数据结构为了实现LR U算法,我们需要定义几个关键的数据结构:3.1.1页面节点结构t y pe de fs tr uc tP age{i n tp ag eI D;//页面I Ds t ru ct Pa ge*n ex t;//下一个节点指针s t ru ct Pa ge*p re v;//上一个节点指针}P ag e;3.1.2内存块结构t y pe de fs tr uc tM emo r y{i n tc ap ac it y;//内存块容量i n ts iz e;//当前存储的页面数量P a ge*h ea d;//内存块链表头指针P a ge*t ai l;//内存块链表尾指针}M em or y;3.2实验步骤本次实验主要包括以下几个步骤:3.2.1初始化内存块根据实际需求,设置内存块的容量,并初始化链表头指针和尾指针。

3.2.2页面置换每次发生页面访问时,检查访问的页面是否已经在内存块中。

如果在,将该页面移动到链表尾部;如果不在,执行页面置换。

3.2.3页面淘汰当内存块已满时,选择链表头部的页面进行淘汰,将新访问的页面加入链表尾部。

LRU算法详解

LRU算法详解

LRU算法详解⼀、什么是 LRU 算法就是⼀种缓存淘汰策略。

计算机的缓存容量有限,如果缓存满了就要删除⼀些内容,给新内容腾位置。

但问题是,删除哪些内容呢?我们肯定希望删掉哪些没什么⽤的缓存,⽽把有⽤的数据继续留在缓存⾥,⽅便之后继续使⽤。

那么,什么样的数据,我们判定为「有⽤的」的数据呢?LRU 缓存淘汰算法就是⼀种常⽤策略。

LRU 的全称是 Least Recently Used,也就是说我们认为最近使⽤过的数据应该是是「有⽤的」,很久都没⽤过的数据应该是⽆⽤的,内存满了就优先删那些很久没⽤过的数据。

举个简单的例⼦,安卓⼿机都可以把软件放到后台运⾏,⽐如我先后打开了「设置」「⼿机管家」「⽇历」,那么现在他们在后台排列的顺序是这样的:但是这时候如果我访问了⼀下「设置」界⾯,那么「设置」就会被提前到第⼀个,变成这样:假设我的⼿机只允许我同时开 3 个应⽤程序,现在已经满了。

那么如果我新开了⼀个应⽤「时钟」,就必须关闭⼀个应⽤为「时钟」腾出⼀个位置,关那个呢?按照 LRU 的策略,就关最底下的「⼿机管家」,因为那是最久未使⽤的,然后把新开的应⽤放到最上⾯:现在你应该理解 LRU(Least Recently Used)策略了。

当然还有其他缓存淘汰策略,⽐如不要按访问的时序来淘汰,⽽是按访问频率(LFU 策略)来淘汰等等,各有应⽤场景。

本⽂讲解 LRU 算法策略。

⼆、LRU 算法描述LRU 算法实际上是让你设计数据结构:⾸先要接收⼀个 capacity 参数作为缓存的最⼤容量,然后实现两个 API,⼀个是 put(key, val) ⽅法存⼊键值对,另⼀个是 get(key) ⽅法获取 key 对应的 val,如果 key 不存在则返回 -1。

注意哦,get 和 put ⽅法必须都是O(1)的时间复杂度,我们举个具体例⼦来看看 LRU 算法怎么⼯作。

/* 缓存容量为 2 */LRUCache cache = new LRUCache(2);// 你可以把 cache 理解成⼀个队列// 假设左边是队头,右边是队尾// 最近使⽤的排在队头,久未使⽤的排在队尾// 圆括号表⽰键值对 (key, val)cache.put(1, 1);// cache = [(1, 1)]cache.put(2, 2);// cache = [(2, 2), (1, 1)]cache.get(1); // 返回 1// cache = [(1, 1), (2, 2)]// 解释:因为最近访问了键 1,所以提前⾄队头// 返回键 1 对应的值 1cache.put(3, 3);// cache = [(3, 3), (1, 1)]// 解释:缓存容量已满,需要删除内容空出位置// 优先删除久未使⽤的数据,也就是队尾的数据// 然后把新的数据插⼊队头cache.get(2); // 返回 -1 (未找到)// cache = [(3, 3), (1, 1)]// 解释:cache 中不存在键为 2 的数据cache.put(1, 4);// cache = [(1, 4), (3, 3)]// 解释:键 1 已存在,把原始值 1 覆盖为 4// 不要忘了也要将键值对提前到队头三、LRU 算法设计分析上⾯的操作过程,要让 put 和 get ⽅法的时间复杂度为 O(1),我们可以总结出 cache 这个数据结构必要的条件:查找快,插⼊快,删除快,有顺序之分。

c++实现操作系统LUR算法

c++实现操作系统LUR算法

操作系统实验报告/** lru.cpp*/#include"lru.h"LRUStack::LRUStack(int mL){if (mL <= 0){cout << "栈最大值错误, 退出" << endl;exit(-1);}this->max_length = mL;this->pHead = new LRUStack();this->pNext = this->pHead;this->pHead->pNext = nullptr;this->length = 0;}/** 根据被访问数据的id(cache)查找其在栈中的位置 * 返回其所在栈的位置pos*/int LRUStack::findStackById(int cache) const {if (this->length == 0)return -1;int pos = 0;// 遍历栈LRUStack *pTemp = this->pHead;while (nullptr != (pTemp = pTemp->pNext)){if (cache == pTemp->cacheId)return pos; // 查找成功pos++;}return -1; // 查找失败}/** 按照结点位置查找结点* 返回结点本身*/LRUStack *LRUStack::findStackByPos(int pos) const{if (pos > this->length || pos < 0)return nullptr;LRUStack *p = this->pHead;for (int i = 0; i < pos + 1; i++)p = p->pNext;return p;}// 在栈尾部追加节点void LRUStack::pushStack(int cache){int pos = this->findStackById(cache);if (pos != -1) // 访问的数据命中, 将其调到栈第一个栈顶{cout << "访问的页号" << cache << "命中! ";// 将被访问的结点调到栈顶 (先将其删除, 再重新入栈, 这样就将缓存数据调到栈顶)LRUStack *p = this->findStackByPos(pos);LRUStack *pFront = this->findStackByPos(pos - 1);LRUStack *pBack = this->findStackByPos(pos + 1);if (pos == 0) // 栈底{delete p;p = nullptr;if (this->length == 1)this->pNext = this->pHead;elsethis->pHead->pNext = pBack;}else if (pos == this->length - 1) // 栈顶, 则什么都不做return;else{delete p;p = nullptr;pFront->pNext = pBack;}this->length--;this->pushStack(cache);}else// 访问的数据为新数据, 插入头部{// 当栈满时, 出栈一次if (this->length == this->max_length)this->popStack();// 访问的新数据入栈LRUStack *pNew = new LRUStack();pNew->cacheId = cache;this->pNext->pNext = pNew;pNew->pNext = nullptr;this->pNext = pNew;this->length++;}}// 删除末尾结点(最近最久未使用的结点)void LRUStack::popStack(){if (this->length == 0)return;else if (this->length == 1){delete this->pHead->pNext;this->pNext = this->pHead;this->pNext->pNext = nullptr;}else{LRUStack *pBegin2 = this->pHead; // 开始第2个结点for (int i = 0; i < 2; i++)pBegin2 = pBegin2->pNext;// 删除第一个结点, 也就是栈底结点this->pHead->pNext->pNext = nullptr;delete this->pHead->pNext;// 栈底指针指向第二个结点this->pHead->pNext = pBegin2;}this->length--;/*LRUStack *pEnd2 = this->pHead; // 倒数第二个结点for (int i = 0; i < this->length - 1; i++)pEnd2 = pEnd2->pNext;if (pEnd2 == this->pHead) // 当栈长等于1时, for循环不执行, 所以pEnd2 == pHead {delete this->pNext;this->pNext = this->pHead;this->pNext->pNext = nullptr;}else // 栈长度大于1{delete this->pNext;this->pNext = pEnd2;this->pNext->pNext = nullptr;}this->length--;*/}// 输出栈void LRUStack::displayList() const{LRUStack *pTemp = this->pHead;while (nullptr != (pTemp = pTemp->pNext)){cout << pTemp->cacheId << "\t";}cout << endl;}UserAccess::UserAccess(const LRUStack lru){this->lruStack = lru;}// 在区间 [minPageId, maxPageId) 内的页号随机访问, 总共访问 countAccess 次void UserAccess::simulationAccess(const int countAccess, const int minPageId, const int maxPageId) {srand((unsigned int)time(nullptr));for (int i = 0; i < countAccess; i++){int randPage = rand() % (maxPageId - minPageId) + minPageId; // 随机访问的数据页号cout << "访问数据" << randPage << ":";this->lruStack.pushStack(randPage);cout << endl << "数据缓存栈 : " << this->lruStack << endl;}}/** lru.h* 1.建立一个缓存数据栈* 2.新数据被访问时将其入栈;* 3.每当缓存命中(即缓存数据被访问),则将命中数据移到栈顶.* 4.当栈满时,将栈顶的数据丢弃.*/#ifndef _LRU_H_#define_LRU_H_#pragma once#include<iostream>#include<ctime>#include<vector>using namespace std;//class LRUStack{private:LRUStack *pHead, *pNext; // 栈底, 栈顶/结点的指针域int cacheId; // 被访问缓存数据的页号id(结点的数据域)int length; // 栈长度int max_length; // 栈允许的最大长度public:LRUStack(){} // 结点LRUStack(int mL); // 栈int findStackById(int cache) const; // 根据页号查找其在栈中的位置LRUStack *findStackByPos(int pos) const; // 根据位置查找结点并返回结点void pushStack(int cache); // 进栈void popStack(); // 出栈(最近最久未使用的结点)void displayList() const; // 输出栈friend ostream &operator<<(ostream &out, const LRUStack &a) // 输出栈{LRUStack *pTemp =a.pHead;while (nullptr != (pTemp = pTemp->pNext)){out << pTemp->cacheId << " ";}out << endl;return out;六、实验存在问题和解决办法。

cache缓存淘汰算法--LRU算法

cache缓存淘汰算法--LRU算法

缓存淘汰算法--LRU算法1. LRU1.1. 原理LRU(Least recently used,最近最少使用)算法根据数据的历史访问记录来进行淘汰数据,其核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高”。

1.2. 实现最常见的实现是使用一个链表保存缓存数据,详细算法实现如下:1. 新数据插入到链表头部;2. 每当缓存命中(即缓存数据被访问),则将数据移到链表头部;3. 当链表满的时候,将链表尾部的数据丢弃。

1.3. 分析【命中率】当存在热点数据时,LRU的效率很好,但偶发性的、周期性的批量操作会导致LRU命中率急剧下降,缓存污染情况比较严重。

【复杂度】实现简单。

【代价】命中时需要遍历链表,找到命中的数据块索引,然后需要将数据移到头部。

2. LRU-K2.1. 原理LRU-K中的K代表最近使用的次数,因此LRU可以认为是LRU-1。

LRU-K的主要目的是为了解决LRU算法“缓存污染”的问题,其核心思想是将“最近使用过1次”的判断标准扩展为“最近使用过K次”。

2.2. 实现相比LRU,LRU-K需要多维护一个队列,用于记录所有缓存数据被访问的历史。

只有当数据的访问次数达到K次的时候,才将数据放入缓存。

当需要淘汰数据时,LRU-K会淘汰第K次访问时间距当前时间最大的数据。

详细实现如下:1. 数据第一次被访问,加入到访问历史列表;2. 如果数据在访问历史列表里后没有达到K次访问,则按照一定规则(FIFO,LRU)淘汰;3. 当访问历史队列中的数据访问次数达到K次后,将数据索引从历史队列删除,将数据移到缓存队列中,并缓存此数据,缓存队列重新按照时间排序;4. 缓存数据队列中被再次访问后,重新排序;5. 需要淘汰数据时,淘汰缓存队列中排在末尾的数据,即:淘汰“倒数第K次访问离现在最久”的数据。

LRU-K具有LRU的优点,同时能够避免LRU的缺点,实际应用中LRU-2是综合各种因素后最优的选择,LRU-3或者更大的K值命中率会高,但适应性差,需要大量的数据访问才能将历史访问记录清除掉。

置换算法lru模拟设计

置换算法lru模拟设计

置换算法lru模拟设计一、概述置换算法(Replacement Algorithm)是一种常用的缓存管理策略,其中 LRU (Least Recently Used)算法是一种常见的策略,用于决定何时淘汰最不常用的数据。

本篇文章将详细介绍如何使用模拟设计实现 LRU 算法。

二、算法原理LRU 算法的基本原理是,当缓存满时,选择最不常用的数据淘汰。

在计算机科学中,常用的 LRU 算法实现方式有三种:FIFO(First In First Out,先进先出)、LFU(Least Frequently Used,最不常用)和基于时间的 LRU。

其中基于时间的 LRU 算法由于其简单易实现,得到了广泛的应用。

三、模拟设计本节将介绍如何使用模拟设计实现 LRU 算法。

模拟设计通常使用一个数组和两个指针来实现。

其中,数组用于存储缓存中的数据,两个指针分别指向最不常用数据和当前头部的位置。

每次有新的数据被插入缓存时,都需要判断其是否已经在缓存中存在,如果存在则移动到尾部,如果不存在则插入到头部。

同时,需要更新头部的指针。

当需要淘汰数据时,选择头部指针所指向的数据进行淘汰。

四、代码实现以下是一个简单的 Python 代码实现:```pythonclass LRUCache:def __init__(self, capacity):self.capacity = capacityself.cache = {}self.head = Noneself.tail = Nonedef get(self, key):if key not in self.cache:return -1self.cache[key].move_to_head()return self.cache[key].valuedef put(self, key, value):if key in self.cache:self.cache[key].move_to_tail()new_node = Node(key, value)if self.head is None:self.head = new_nodeself.tail = new_nodeelse:new_node.move_to_head()prev_node = self.headwhile prev_node.next:prev_node = prev_node.nextprev_node.next = new_nodeself.tail = new_nodeself.cache[key] = new_nodeif len(self.cache) > self.capacity:tail = self.tail.prevdel self.cache[tail.key]if tail == self.head:self.head = Noneself.tail = None```在这个实现中,我们使用了一个 Node 类来表示缓存中的数据节点,其中包含了键值、值和位置信息。

存储管理实验报告

存储管理实验报告

一、实验目的1. 理解操作系统存储管理的概念和作用。

2. 掌握存储管理的基本算法和策略。

3. 通过实验,加深对存储管理原理的理解,提高实际操作能力。

二、实验环境1. 操作系统:Windows 102. 软件环境:虚拟机软件VMware Workstation 153. 实验平台:Linux系统三、实验内容1. 存储管理概述2. 页式存储管理3. 段式存储管理4. 分段分页存储管理5. 存储管理算法四、实验步骤1. 页式存储管理实验(1)设置虚拟内存:在Linux系统中,使用`cat /proc/meminfo`命令查看内存信息,然后使用`vmstat`命令查看虚拟内存的使用情况。

(2)编写实验程序:使用C语言编写一个简单的程序,模拟页式存储管理过程。

(3)运行实验程序:编译并运行实验程序,观察程序运行过程中页面的分配、置换和回收过程。

2. 段式存储管理实验(1)设置虚拟内存:同页式存储管理实验。

(2)编写实验程序:使用C语言编写一个简单的程序,模拟段式存储管理过程。

(3)运行实验程序:编译并运行实验程序,观察程序运行过程中段页的分配、置换和回收过程。

3. 分段分页存储管理实验(1)设置虚拟内存:同页式存储管理实验。

(2)编写实验程序:使用C语言编写一个简单的程序,模拟分段分页存储管理过程。

(3)运行实验程序:编译并运行实验程序,观察程序运行过程中段页的分配、置换和回收过程。

4. 存储管理算法实验(1)编写实验程序:使用C语言编写一个简单的程序,模拟不同的存储管理算法(如FIFO、LRU、LFU等)。

(2)运行实验程序:编译并运行实验程序,观察不同算法在页面分配、置换和回收过程中的表现。

五、实验结果与分析1. 页式存储管理实验实验结果表明,页式存储管理可以将大程序离散地存储在内存中,提高内存利用率。

但页式存储管理也存在页面碎片问题,导致内存碎片化。

2. 段式存储管理实验实验结果表明,段式存储管理可以将程序按照逻辑结构划分为多个段,提高了内存的利用率。

LRU算法总结

LRU算法总结

LRU算法总结LRU算法总结⽆论是哪⼀层次的缓存都⾯临⼀个同样的问题:当容量有限的缓存的空闲空间全部⽤完后,⼜有新的内容需要添加进缓存时,如何挑选并舍弃原有的部分内容,从⽽腾出空间放⼊这些新的内容。

解决这个问题的算法有⼏种,如最近使⽤算法(LRU)、先进先出算法(FIFO)、最近最少使⽤算法(LFU)、⾮最近使⽤算法(NMRU)等,这些算法在不同层次的缓存上执⾏时拥有不同的效率和代价,需根据具体场合选择最合适的⼀种。

最近使⽤算法,顾名思义,可以将其理解为如果数据最近被访问过,那么将来被访问的⼏率也很⾼。

它的实现有多种⽅式,⽐如LRU、LRU-K、Two queues、Mutiple queues等。

LRU常⽤的实现是使⽤下图中的⽅式,往头部加⼊新的数据,如果该数据存在则将其放到头部,如果加⼊时已满,则从底部淘汰掉数据。

这种⽅式虽然简单,在频繁访问热点数据的时候效率⾼,但是它的缺点在于如果是偶尔的批量访问不同的数据时其命中率就会很低。

⽐如我频繁的访问A,接着访问不同的数据直到A被淘汰,此时我再访问A,则不得不⼜再次把A加⼊到Cache中,显然这种⽅式是不合时宜的,因为A已经访问了很多次了,不应该将其淘汰⽽把⼀堆只访问⼀次的数据加⼊到Cache中。

LRU-K上⾯的LRU只会将最近使⽤的⼀次加⼊到缓存,因此需要将其进⾏优化,变成缓存k次的才加⼊到缓存中,于是我们需要维护⼀个历史队列,纪录其数据对应的访问次数,其根据访问次数来进⾏淘汰,如果访问次数达到了k次才从历史队列中删除加⼊到缓存中,缓存按照LRU的规则来淘汰数据。

它的命中率要⽐LRU要⾼,但是因为需要维护⼀个历史队列,因此内存消耗会⽐LRU多。

实际应⽤中LRU-2是综合各种因素后最优的选择,LRU-3或者更⼤的K值命中率会⾼,但适应性差,需要⼤量的数据访问才能将历史访问记录清除掉。

Two queues(2Q)和LRU-k类似,但不同的是,其有两个缓存队列,⼀个是FIFO队列,⼀个是LRU队列。

JAVA实现LRU算法

JAVA实现LRU算法

JAVA实现LRU算法最近⾯了阿⾥的外包吧,居然也要在线敲代码了,那叫⼀个紧张啊。

题⽬就是实现⼀个LRU算法的缓存。

外包居然要求也这么⾼了,哎。

还好,LRU是我⼤学⽼师布置的⼀道题⽬,当然我⽤C语⾔实现的,算法原理那是⼀清⼆楚,可是⾯试的时候就脑⼦⼀⽚空⽩了。

好在,边敲代码,边思考,就慢慢想起来了,下⾯是我的代码。

仅供参考/*** 设计和构建⼀个“最近最少使⽤”LRU 缓存,该缓存会删除最近最少使⽤的项⽬。

* 缓存应该从键映射到值(允许你插⼊和检索特定键对应的值),并在初始化时指定最⼤容量。

* 当缓存被填满时,它应该删除最近最少使⽤的项⽬。

* 考虑多线程操作下的操作安全和性能。

*/public class LRUCache{private int maxSize;/*** 存储缓存数据*/private ConcurrentHashMap<String,Object> map = new ConcurrentHashMap<>();/****存储缓存key列表*/private LinkedList<String> list;LRUCache(){}LRUCache(int maxSize){this.maxSize = maxSize;this.list = new LinkedList<>(maxSize);}/*** @param key 缓存key@return缓存值*/synchronized Object getVal(String key){//1.从map⾥取数据Object obj = map.get(key);//2.将key置于list的尾部(表⽰最近被访问过了)if(obj != null){addOrRefreshKey(key);}}synchronized void putVal(String key,Object val){//1.设置val到map中//2.将key置于list的尾部(表⽰最近被访问过了)//3.需要做判断是否list.size()>maxSize。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
相关文档
最新文档