公司使用的文件缓存经常出现大量的并发冲突,主要原因有两个:一个是读取文件时刚好文件被删除了,这样会抛出找不到文件的异常; 另一个是资源权限争抢的问题,可能会导致没有权限操作的情况。
    ReaderWriterLock类实现了多用户读/单用户写的同步访问机制,可以使用此类对文件的读写进行加锁操作,因为文件缓存一般是大量读少量写的情况,所以非常适合使用ReaderWriterLock。
    1、读缓存文件时使用AcquireReaderLock方法,并设置1000ms超时操作。

        private string readfile(string filename)
        {
            FileStream fs = null;
            try
            {
                rwLock.AcquireReaderLock(1000);//获取读锁
                fs = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                byte[] buf = new byte[fs.Length];
                fs.Read(buf, 0, (int)fs.Length);
                string xml = Encoding.UTF8.GetString(buf);
                return xml;
            }
            catch (FileNotFoundException)//2008-01-24 add
            {
                return null;
            }
            finally
            {
                if (fs != null)
                {
                    fs.Close();
                    fs.Dispose();
                    fs = null;
                }
                rwLock.ReleaseReaderLock();//释放读锁
            }
        }

2、添加缓存文件时使用AcquireWriterLock方法获取写锁。

        public void Add(string key, object value)
        {
            if (key == null) return;
            if (value == null)
            {
                Remove(key);
                return;
            }
            string fn = makefilename(makekey(key));
            string dir = Path.GetDirectoryName(fn);
            if (!Directory.Exists(dir)) Directory.CreateDirectory(dir);
            string xml = makevalue(value);
            //File.WriteAllText(fn, xml, Encoding.UTF8);

            FileStream fs = null;
            try
            {
                rwLock.AcquireWriterLock(1000);//获取写锁
                fs = new FileStream(fn, FileMode.Create, FileAccess.Write, FileShare.Read);
                byte[] buf = Encoding.UTF8.GetBytes(xml);
                fs.Write(buf, 0, buf.Length);
            }
            finally
            {
                if (fs != null)
                {
                    fs.Close();
                    fs.Dispose();
                    fs = null;
                }
                rwLock.ReleaseWriterLock();//释放写锁
            }

        }

3、在删除缓存文件时也通过AcquireWriterLock获取写锁。

        public void Remove(string key)
        {
            if (key == null) return;
            string fileName = makefilename(makekey(key));

            try
            {
                rwLock.AcquireWriterLock(1000);//获取写锁
                File.Delete(fileName);
            }
            finally
            {
                rwLock.ReleaseWriterLock();//释放写锁
            }


        }

另外还写了一个测试程序对优化了的文件缓存进行并发访问测试。

//#define usetry
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Diagnostics;
namespace CJB.Caching.FileSystem.Test
{
    class Program
    {
        static long ElapsedTime = 0;
        static readonly object ElapsedTimeLock = new object();
        static long Counter = 0;

        static void Main(string[] args)
        {
            Thread t1 = new Thread(ReadTest);
            Thread t2 = new Thread(ReadTest);
            Thread t3 = new Thread(ReadTest);
            Thread t4 = new Thread(WriteTest);
            Thread t5 = new Thread(WriteTest);
            t1.Start(); //t1.Join();
            t2.Start(); //t2.Join();
            t3.Start(); //t3.Join();
            t4.Start(); //t4.Join();
            t5.Start(); //t5.Join();


            Console.ReadLine();
            Console.WriteLine(String.Format("程序完成调用{0}次数", Counter));
            Console.WriteLine(String.Format("程序运行时间{0}毫秒", ElapsedTime));
            while (Console.ReadLine() != "q")
            {
                Console.WriteLine("请输入q退出程序");
            }
        }

        static void ReadTest()
        {
            TCache<string> tCache = new TCache<string>(TCacheType.FSCacheTest);
            string cacheKey = tCache.GetCacheKey("billok");

            Stopwatch sw = null;
            for (int i = 0; i < 1000; i++)
            {
                sw = Stopwatch.StartNew();
#if(usetry)
                try
                {
#endif
                    string result = tCache.GetValue(cacheKey, delegate() { return "ReadTest" + i.ToString(); });
                    Console.WriteLine(result);
#if(usetry)
                }
                catch { }
#endif
                long ms = sw.ElapsedMilliseconds;
                lock (ElapsedTimeLock)
                {
                    ElapsedTime += ms;
                }
                Interlocked.Increment(ref Counter);
                Thread.Sleep(10);
            }
        }

        static void WriteTest()
        {
            TCache<string> tCache = new TCache<string>(TCacheType.FSCacheTest);
            string cacheKey = tCache.GetCacheKey("billok");

            Stopwatch sw = null;
            for (int i = 0; i < 1000; i++)
            {
                sw = Stopwatch.StartNew();
#if(usetry)
                try
                {
#endif
                    tCache.Remove(cacheKey);
                    Console.WriteLine("删除" + cacheKey);
#if(usetry)
                }
                catch { }
#endif
                long ms = sw.ElapsedMilliseconds;
                lock (ElapsedTimeLock)
                {
                    ElapsedTime += ms;
                }
                Interlocked.Increment(ref Counter);
                Thread.Sleep(10);
            }
        }
    }
}

测试使用了Interlocked类来同步记录总共的读写次数,使用lock来同步记录总共耗时。
注意使用Thread.Sleep(10);可以保证测试程序的并发量,防止在一个非常小的一个时间片中就耗掉大量的测试操作。

转载于:https://www.cnblogs.com/chenjunbiao/archive/2008/01/25/1760222.html

使用ReaderWriterLock优化文件缓存相关推荐

  1. ASP.NET性能优化之构建自定义文件缓存

    ASP.NET的输出缓存(即静态HTML)在.NET4.0前一直是基于内存的.这意味着如果我们的站点含有大量的缓存,则很容易消耗掉本机内存.现在,借助于.NET4.0中的OutputCacheProv ...

  2. 【精华】Asp优化之缓存技术

    一.何谓ASP缓存/为什么要缓存 当你的web站点采用asp技术建立的初期,可能感觉到的是asp动态网页技术带来的便利性,以及随意修改性.自如的http控制.但是,随着访问量的增加,你一定会发现自己的 ...

  3. nginx静态文件缓存

    nginx的一大功能就是完成静态资源的分离部署,减轻后端服务器的压力,如果给这些静态资源再加一级nginx的缓存,可以进一步提升访问效率. 第一步:添加nginx.conf的http级别的缓存配置 # ...

  4. Mysql高级-应用优化,查询缓存优化,锁

    文章目录 1. 应用优化 1.1 使用连接池 1.2 减少对MySQL的访问 1.2.1 避免对数据进行重复检索 1.2.2 增加cache层 1.3 负载均衡 1.3.1 利用MySQL复制分流查询 ...

  5. WIN10的传递优化文件是个什么鬼?能删除吗?

    Win10正式版系统使用时间长了以后,电脑磁盘总会产生一些冗余的文件和磁盘碎片,我们可以用一些工具软件对硬盘进行优化和处理,其实利用系统自带的工具也可以清理磁盘的,但在操作过程中,我们常常会看到一个名 ...

  6. php数据库缓存类,常见php数据文件缓存类汇总

    本文实例汇总了常见php数据文件缓存类.分享给大家供大家参考.具体分析如下: 数据文件缓存的做法我们常用的有php文件缓存与利用memcache来缓存数据,下面面我分别总结了memcache缓存数据与 ...

  7. android 内部存储 清空,Android清空应用内部文件缓存

    Android应用中加载的图片以及一些数据缓存怎么清掉呢?最近在做项目中遇到了这个问题,网上搜了一下找到了不少的源代码,综合了这些源码,下面给大家说一下吧,怎么有效的清除应用内存的缓存信息? 清除应用 ...

  8. 缓存处理类(MemoryCache结合文件缓存)

    想提升站点的性能,于是增加了缓存,但是站点不会太大,于是不会到分布式memcached的缓存和redis这个nosql库,于是自己封装了.NET内置的缓存组件 原先使用System.Web.Cachi ...

  9. android文件缓存,并SD卡创建目录未能解决和bitmap内存溢出解决

    1.相关代码: 加入权限: <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" ...

最新文章

  1. Hibernate第一次课(1)
  2. kafka是什么_技术面试官问:Kafka为什么速度那么快?
  3. vim剪切指定行_10 分钟上手 Vim,常用命令大盘点
  4. 本田思域自动挡的使用技巧
  5. MFC的Dialogbox多行文本框(CEdit)有最大字符限制,默认最大显示长度
  6. 第6章 访问权限控制
  7. 虚拟化试题1-网络和存储
  8. 亲身体验 DDOS(拒绝服务)攻击硬防DIY
  9. 科技爱好者周刊:第 78 期
  10. Linux之iptables防火墙
  11. BUUCTF-MISC-被劫持的神秘礼物~梅花香之苦寒来
  12. C# ActionT 委托
  13. Windwos注册表案例(友尽百科)
  14. mac 终端 创建java文件_第一个 终端Java程序 (Mac)
  15. IdentityServer3 v1文档
  16. Cocos 配置 FMOD EX
  17. android -fanfou-project-source study
  18. 【会议记录】2022北京网络安全大会-杨珉-软件供应链安全治理之漏洞补丁:现状及应对方案
  19. PMP的报考流程以及考试流程
  20. 基于javaweb的药品进货销售管理系统(java+ssm+html+js+jsp+mysql)

热门文章

  1. Redis的字典扩容与ConcurrentHashMap的扩容策略比较
  2. windows7 下的日期没有internet时间的选项卡
  3. Vmware 10 安装
  4. Mysql中文乱码问题完美解决方案
  5. [java]窗口的创建
  6. c++Primer再学习-练习Todo
  7. oracle_dataGuard_11G
  8. Python学习笔记011——内置函数exec()
  9. 你想要的iOS 小技巧总结
  10. 项目展示文案生成设计