title author date CreateTime categories
C# dotnet 线程不安全的弱引用缓存
lindexi
2019-11-7 9:45:5 +0800
2019-11-06 16:58:11 +0800
dotnet C#

很多逻辑都会使用内存做缓存,这样可以提高运行效率。但是有一些逻辑很少会执行,但是如果有执行就是频繁调用。如我写了文本编辑器,在我打开文件的逻辑,将会不断调用正则判断逻辑,而平时编辑很少会调用。如果将这部分的正则逻辑缓存了,那么可以提升打开文件速度,但是在打开文件之后这部分就成为内存垃圾了。本文给大家一个弱引用缓存,也就是在频繁使用时从内存获取,在不使用时会被回收,这样可以提升性能也能减少内存使用

因为作为缓存,如果需要考虑线程安全,那么这部分的逻辑就复杂了。在不考虑线程安全下,开发一个弱引用缓存还是很简单

首先是创建一个字典,这个字典包含弱引用,这样在获取之前可以先从字典获取

        private readonly Dictionary<object, WeakReference<object>> _cacheList =
new Dictionary<object, WeakReference<object>>();

在用户获取之前,需要知道,可能内存回收了。所以使用方法是获取或创建,也就是这个方法不能保证只有第一次获取时才创建,而是看内存回收

 public T GetOrCreate<T>(object key, Func<T> createFunc)

如果此时可以从内存获取,那么直接返回

            if (_cacheList.TryGetValue(key, out var weakReference))
{
if (weakReference.TryGetTarget(out var value))
{
return (T) value;
}
}

如果不能从内存获取,就需要调用方法创建

            var t = createFunc();
weakReference = new WeakReference<object>(t);
_cacheList[key] = weakReference;
return t;

所以获取方法如下

        /// <summary>
/// 从缓存获取或在没有获取到创建
/// </summary>
public T GetOrCreate<T>(object key, Func<T> createFunc)
{
if (_cacheList.TryGetValue(key, out var weakReference))
{
if (weakReference.TryGetTarget(out var value))
{
return (T) value;
}
} var t = createFunc();
weakReference = new WeakReference<object>(t);
_cacheList[key] = weakReference;
return t;
}

因为每次给一个 key 也不好用,有一些对象只需要一个类只有存在一个,可以使用类型作为 key 可以再写另一个方法

        /// <summary>
/// 从缓存获取或在没有获取到创建
/// </summary>
public T GetOrCreate<T>(Func<T> createFunc)
{
var type = typeof(T);
return GetOrCreate(type, createFunc);
}

这个线程不安全的弱引用缓存所有代码很少,可以直接复制在项目使用

    /// <summary>
/// 弱引用缓存
/// </summary>
public class WeakReferenceCache
{
/// <summary>
/// 从缓存获取或在没有获取到创建
/// </summary>
public T GetOrCreate<T>(object key, Func<T> createFunc)
{
if (_cacheList.TryGetValue(key, out var weakReference))
{
if (weakReference.TryGetTarget(out var value))
{
return (T) value;
}
} var t = createFunc();
weakReference = new WeakReference<object>(t);
_cacheList[key] = weakReference;
return t;
} /// <summary>
/// 从缓存获取或在没有获取到创建
/// </summary>
public T GetOrCreate<T>(Func<T> createFunc)
{
var type = typeof(T);
return GetOrCreate(type, createFunc);
} private readonly Dictionary<object, WeakReference<object>> _cacheList =
new Dictionary<object, WeakReference<object>>();
}

此方法是线程不安全的,请不要在多线程下使用此方法,可以通过 线程静态字段 让一个线程有一个实例

本文代码放在 github 欢迎小伙伴访问

2019-11-7-C#-dotnet-线程不安全的弱引用缓存的更多相关文章

  1. 《Android开发艺术探索》读书笔记 (11) 第11章 Android的线程和线程池

    第11章 Android的线程和线程池 11.1 主线程和子线程 (1)在Java中默认情况下一个进程只有一个线程,也就是主线程,其他线程都是子线程,也叫工作线程.Android中的主线程主要处理和界 ...

  2. 《Android开发艺术探索》第11章 Android的线程和线程池

    第11章 Android的线程和线程池 11.1 主线程和子线程 (1)在Java中默认情况下一个进程只有一个线程,也就是主线程,其他线程都是子线程,也叫工作线程.Android中的主线程主要处理和界 ...

  3. EOJ Monthly 2019.11 E. 数学题(莫比乌斯反演+杜教筛+拉格朗日插值)

    传送门 题意: 统计\(k\)元组个数\((a_1,a_2,\cdots,a_n),1\leq a_i\leq n\)使得\(gcd(a_1,a_2,\cdots,a_k,n)=1\). 定义\(f( ...

  4. [New!!!]欢迎大佬光临本蒟蒻的博客(2019.11.27更新)

    更新于2019.12.22 本蒟蒻在博客园安家啦!!! 本蒟蒻的博客园主页 为更好管理博客,本蒟蒻从今天开始,正式转入博客园. 因为一些原因,我的CSDN博客将彻底不会使用!!!(带来不便,敬请谅解) ...

  5. 2019.11.9 csp-s 考前模拟

    2019.11.9 csp-s 考前模拟 是自闭少女lz /lb(泪奔 T1 我可能(呸,一定是唯一一个把这个题写炸了的人 题外话: 我可能是一个面向数据编程选手 作为一个唯一一个写炸T1的人,成功通 ...

  6. C++11 左值、右值、右值引用详解

    C++11 左值.右值.右值引用详解 左值.右值 在C++11中所有的值必属于左值.右值两者之一,右值又可以细分为纯右值.将亡值. 在C++11中可以取地址的.有名字的就是左值,反之,不能取地址的.没 ...

  7. ThreadLocal 定义,以及是否可能引起的内存泄露(threadlocalMap的Key是弱引用,用线程池有可能泄露)

    ThreadLocal 也可以跟踪一个请求,从接收请求,处理请求,到返回请求,只要线程不销毁,就可以在线程的任何地方,调用这个参数,这是百度二面的题目,参考: Threadlocal 传递参数(百度二 ...

  8. Volatile如何保证线程可见性之总线锁、缓存一致性协议

    基础知识回顾 下图给出了假想机的基本设计.中央处理单元(CPU)是进行算术和逻辑操作的部件,包含了有限数量的存储位置--寄存器(register),一个高频时钟.一个控制单元和一个算术逻辑单元. 时钟 ...

  9. dotnet 线程静态字段

    在 dotnet 程序提供了一个好用的特性,可以让字段作为线程的静态字段,也就是在相同线程的所有代码访问的静态字段是相同对象,但不同线程访问的时候是不同的 在 .NET 程序可以使用 ThreadSt ...

  10. 使用C++11安全的在线程中控制UI

    本篇文章由:http://www.sollyu.com/using-the-c11-secure-online-process-control-ui/ 说明 首先这里使用的是 Visual Studi ...

随机推荐

  1. JZOJ5143:无心行挽

    Description “What’s left to do when we’ve lost all hope?”“若内心万念俱灰,是否注定无心行挽?”------来自网易云音乐<Golden ...

  2. NX二次开发-创建直线UF_CURVE_create_line与NXOpen->CreateLine

    NX11+VS2013 #include <uf.h> #include <uf_curve.h> #include <NXOpen/CurveCollection.hx ...

  3. NX二次开发-UFUN链表UF_MODL_create_list等用法

    NX9+VS2012 #include <uf.h> #include <uf_modl.h> #include <uf_curve.h> #include < ...

  4. 数据结构C++版-队列

    一.概念 分类: 二.补充说明 1.<面向对象的队列设计>课程问答: 首先要明确数据结构和数据存储结构的概念. 数据结构是指数据对象之间的逻辑关系,例如二叉树,队列,栈等,而数据存储结构是 ...

  5. https://segmentfault.com 一个学习网站

    https://segmentfault.com一个学习网站

  6. [14]APUE:API for Mysql

    库:/usr/lib64/libmysqlclient.so.#.#... 头文件:/usr/lib64/mysql/mysql.h 一.建立连接 MYSQL *mysql_init(MYSQL *) ...

  7. 剑指offer——30栈的压入、弹出序列

    题目描述 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序.假设压入栈的所有数字均不相等.例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压 ...

  8. 20140403 opencv GPU安装

    1.  查看本机配置,查看显卡类型是否支持NVIDIA GPU,本机显卡为NVIDIA GeForce 8400 GS: 2.  从http://www.nvidia.cn/Download/inde ...

  9. Linux系统搭建Red5服务器

    Linux系统搭建Red5服务器 Red5 是 支持Windows,Linux等多平台的RTMP流媒体服务器,Windows下搭建相对容易,图形界面操作比较简单,Linux服务器的环境下没有图形界面, ...

  10. Impala查询执行过程