MemoryCache 使用不当导致的一个 BUG

MemoryCache 使用不当导致的一个 BUG

Intro

前几天发现代码里的一个 BUG,原因是 MemoryCache 使用不当,可以对于很多人来说可能都知道,但还是想分享记录一下,避免以后写出同样的 BUG

Sample

直接来看下面的示例吧

await using var services = new ServiceCollection().AddMemoryCache().BuildServiceProvider();Console.WriteLine("----- Bad -----");
GetValidValues(5).Dump();
GetValidValues(8).Dump();List<int> GetValidValues(int threhold)
{var memoryCache = services.GetRequiredService<IMemoryCache>();var values = memoryCache.GetOrCreate("test1", entry =>{return Enumerable.Range(1, 10).ToList();});values.RemoveAll(x => x > threhold);return values;
}

上面的 Dump 是一个扩展方法就是把 list 内的元素输出出来,实现如下:

public static void Dump(this List<int> values)
{var value = string.Join(",", values);Console.WriteLine(value);
}

好了,来想一下上面的输出结果会是什么吧,期望的结果应该是每次都输出小于等于输入的值,实际是什么样的呢?实际输出结果如下:

Fix

可以看到第二次输出的结果和我们的期望不同,之所以会出现上面的问题是因为 MemoryCache 的对象是直接保存在内存中的对象,缓存不发生变化时每次都是返回同一个对象,如果发生修改后面再获取的就是修改后的状态了,所以正确的做法应该要返回一个新的对象而不是修改原来的对象,一个修改方法如下:

List<int> GetValidValues(int threhold)
{var memoryCache = services.GetRequiredService<IMemoryCache>();var values = memoryCache.GetOrCreate("test", entry =>{return Enumerable.Range(1, 10).ToList();});return values.Where(v => v <= threhold).ToList();
}

修改后的输出结果如下:

More

MemoryCache 背后实际是一个 ConcurrentDictionary,value 是一个带着过期时间的对象 CacheEntry

在不过期,没有发生变化的时候每次返回都是同一个对象,作为缓存对象,应该进行只读操作,不应该修改缓存的对象,如果需要修改则应创建新的对象,而非使用原来的对象。

References

  • https://github.com/dotnet/runtime/blob/main/src/libraries/Microsoft.Extensions.Caching.Memory/src/MemoryCache.cs#L26

  • https://github.com/dotnet/runtime/blob/main/src/libraries/Microsoft.Extensions.Caching.Memory/src/CacheEntry.cs

  • https://github.com/WeihanLi/SamplesInPractice/blob/master/MemoryCacheSample/Program.cs

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/298285.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

22岁少年破解史上最严重网络攻击,拯救全球互联网,三个月后却被FBI逮捕

转自&#xff1a;大数据文摘编译&#xff1a;牛婉杨2017年&#xff0c;一位名叫Marcus Hutchins的少年从有史以来最严重的网络攻击事件“WannaCry 勒索病毒”中拯救了互联网。如果你是个geek&#xff0c;那么你对WannaCry这个名字一定不陌生&#xff0c; 这是一种可以自行传播的…

使用 Git Extensions 简单入门 Git

使用 Git Extensions 简单入门 Git—— 独立观察员 2015.11.25前言关于这个主题&#xff0c;之前我录了段视频教程&#xff0c;在本地看清晰度还可以&#xff0c;但传到优酷上就很不清晰了&#xff0c;即使是后来重制后还是一样不清晰&#xff0c;所以现在想整理成文字版。当然…

各省地图都像些什么?

全世界只有3.14 % 的人关注了爆炸吧知识人们常说中国地图的形状像一只雄鸡&#xff0c;但具体到每一个省区则并没有一个明确的说法。看看下面这一套省区地图对应的有趣的想象&#xff0c;你觉得像还是不像&#xff1f;★安徽有人说安徽像一只斜倒挂着的蝙蝠&#xff0c;你能看出…

Silverlight中摄像头的运用—part2

Silverlight 4 中摄像头的运用—part1将跟踪颜色视作输入 好了&#xff0c;我们能够跟踪到这个颜色了&#xff0c;那这么做的意义是什么呢&#xff1f;实际上&#xff0c;我们可以根据它的位置来移动东西。接下来的例子中&#xff0c;创建的一个球会跟随这个颜色一起移动。你可…

同学,解决下这个 Bug!

一些解决 Bug 的小技巧大家好&#xff0c;我是鱼皮。学编程的过程中&#xff0c;我们会遇到各式各样的 Bug&#xff0c;也常常因为它们而感到头秃。但随着你不断解决 Bug、积累经验&#xff0c;就会发现其实解决 Bug 也是有套路的。今天分享下鱼皮自己总结的解决 Bug 套路&…

如果给你一个亿,你想去干嘛?各专业的科研狗是这样回答的……

全世界只有3.14 % 的人关注了爆炸吧知识“如果现在给你一个亿&#xff0c;你想去做什么&#xff1f;”每天都被穷醒的小天一看到&#xff0c;立马展开了丰富的想象力&#xff1a;首先&#xff0c;当然少不了买买买&#xff0c;将一切之前想要的、不想要的&#xff0c;贵的、更贵…

头文件定义全局变量_5.2 C++局部变量与全局变量 | 输出局部全局变量

C局部变量C局部变量是指&#xff1a;在一个函数内部定义的变量&#xff0c;它只在本函数范围内有效&#xff0c;也就是说只有在本函数内才能使用它&#xff0c;在此函数以外是不能使用这些变量的。同样&#xff0c;在复合语句中定义的变量只在本复合语句范围内有效&#xff0c;…

java float转换成long_在Java中如何将float转换为long或int数据类型?

float f1.2f;double dDouble.parseDouble(String.valueOf(f));System.out.println(d);直接转换会设计到精度问题&#xff0c;所以需要借助字符串 保证不丢失数据www.shufadashi.com防采集。楼主您好&#xff0c;如果float是个整数&#xff0c;强制转换即可&#xff0c;可以捕捉…

Spark 1.2 发布,开源集群计算系统

2019独角兽企业重金招聘Python工程师标准>>> Spark 1.2 发布&#xff0c;此版本包括 172 位贡献者和超过 1000 个 commits。 此版本包括 Spark 核心操作和性能改进&#xff1b;添加新的网络传输子系统&#xff0c;进行了较大的改进&#xff1b;Spark SQL 引入了一个…

[转载].SSRAM、SDRAM和Flash简要介绍

转CalmBright兄的博文&#xff1a;http://www.cnblogs.com/CalmBright/archive/2009/07/19/1526569.html Abstract 在用NIos II 调试sdram遇到了其容量计算的问题&#xff0c;现介绍如下 Introduction 问题1&#xff1a;什么是DRAM、SRAM、SDRAM&#xff1f; 答&#xff1a;名词…

调整 Docker 中 nginx 的日志级别

调整 Docker 中 nginx 的日志级别Intro最近发现我们的一个应用产生了很多日志&#xff0c;而这些日志大多都是 nginx 的 access_log&#xff0c;我们默认会把标准输出收集到 es 里分析应用日志&#xff0c;但是很多都是 access_log 就可能会掩盖掉真实的错误日志&#xff0c;所…

Oracle B-Tree Index 原理

一. B-Tree Index 原理 官网说明&#xff1a; No index structure can satisfy all needs, but the self-balancing B-tree index comes closest to optimizing the performance of searches on large sets of data. Each B-tree node holds multiple keys and pointers. The m…

曾改变世界的最强科学,为什么我们对它的误解却越来越多?

古往今来&#xff0c;我们评价一个人有学识&#xff0c;总是形容&#xff1a;“上知天文下知地理”。也会要求一个人“读万卷书&#xff0c;行万里路”。美国认知心理学家Nora S. Newcombe认为&#xff1a;孩子常常看地图、爱看地图&#xff0c;能提高他们的空间想象力&#xf…

多线程环境下,程序真是危机四伏

姿势在不断的更新迭代&#xff0c; 太卷了。你管这也叫线程安全&#xff1f;最近大意了&#xff0c;竟然想将《面试官&#xff1a;实现一个带值变更通知能力的Dictionary》一文中的临界锁只应用到写操作。内心旁白&#xff1a;读操作又不会修改数据&#xff0c;无论是新值还是旧…

眼见不一定为实!18个神奇的视错觉,看完不相信眼睛系列

全世界只有3.14 % 的人关注了爆炸吧知识来源&#xff1a;普象工业设计小站在家长时间网上冲浪总有时候感觉眼睛出了毛病不信&#xff0c;你看为啥这个明明是个三棱锥怎么突然变成了正方体我是“瞎”了么啊啊啊啊后来&#xff0c;去找了资料才发现这原来是一家幻觉博物馆的展品玩…

怎么用java ee编程_Java EE应用程序入门 - 编程入门网

Java EE应用程序入门时间:2011-07-06 netbeans.org本文将详细介绍使用 EJB 3.0 技术开发企业应用程序的基础知识&#xff0c;而 EJB 3.0 是 Java EE 5 平台的组成部分。本文还将阐述如何通过 EJB 3.0 技术简化开发企业应用程序的流程。本文使用的是 NetBeans IDE 6.0 发行版。先…

vb6 由于超出容量限制 不能创建新事务_分布式限流?你也能轻松玩转(没啥新技术)...

点击蓝色「日拱一兵」关注&#xff0c;持续侦破 Java 技术案件一、什么是限流&#xff1f;为什么要限流&#xff1f;不知道大家有没有做过帝都的地铁&#xff0c;就是进地铁站都要排队的那种&#xff0c;为什么要这样摆长龙转圈圈&#xff1f;答案就是为了限流&#xff01;因为…

Managing Gigabytes--文本压缩

开门见山&#xff0c;文本压缩可以归纳为两大类, 符号方法和字典方法&#xff0c; 下面分别介绍下&#xff1a; 1&#xff09;符号方法&#xff0c;symbolwise method普通编码方式是每个字符都采用相同位数编码&#xff0c; 比如asc码&#xff0c; 每个字符都是8位编码。那么现…

基于事件驱动架构构建微服务第8部分:在应用程序上实现事件溯源

原文链接&#xff1a;https://logcorner.com/building-microservices-through-event-driven-architecture-part8-implementing-eventsourcing-on-application/在本文中&#xff0c;我将讨论应用程序上的事件溯源实现。该层围绕领域并实现用例&#xff08;特定于应用程序的业务规…

我们来聊点成年人的话题!

1 这个话题透漏着成年人都存在的问题&#xff0c;其中心思想行走在道德底线&#xff0c;让人不得不深思&#xff0c;句句入心2 哈哈哈哈哈哈哈哈哈哈哈哈哈画面惊人 图自动漫次元酱3 对不起&#xff0c;我不是你家的鸡&#xff0c;我是一只大鸟&#xff01;&#xff01;&#x…