zoukankan      html  css  js  c++  java
  • 在多线程下请注意代码的安全

    当我们的程序在单一线程运行很正常,但是在多线程下,代码并不是哪么的强键!

    我们编码的时候经常在使用缓存(或者使用设计模式的单件模式),缓存的东西一般是常用或者是运行代价非常昂贵的

     

    下面我们看一个例子:

    说明:yi.Components.YICache是一个管理缓存的Class

          yi.Components. ResourceManager是一个管理公共的资源的Class

     

    yi.Components. ResourceManager下有以下这个方法获取资源信息(这在项目中可能是使用一个XML文件,或者是反序化一个流对象)

    private static Hashtable GetResource()

          {

               String cacheKey = Type.GetType("ResourceManager").ToString();

               Hashtable resources = YICache.Get(cacheKey) as Hashtable;

     

               if (null == resources)

               {

                  resources = new Hashtable();

                 

                  LoadResource(resources); //这里假设做一些非常昂贵的IO操作或者其它操作

                  YICache.Max(cacheKey, resources);

               }

     

               return resources;

           }

    以上哪一段码在单线程下运行的效果正是我们所想要的结果,哪么在多线程下是否是安全呢?

    使用ACT对它进行测试一下,然后再使用监视工具进行监视,其结果并不是我们想要的,

    测试的结果的是:平均运行两次就去执行非常昂贵的IO操作或者是其它操作

     

    这时候你可以会想到,可能有ABC三个线程同时对GetResource()方法进行访问,哪么如果同时有ABC同时对LoadResource()这个方法进行操作.问题可已经找到了,哪么你可能认为上个锁不就完事.

     

    然后将以上代码进行更改如下:

    public static readonly object CacheObject = new object();

           private static Hashtable GetResource()

           {

               string cacheKey = Type.GetType("ResourceManager").ToString();

               Hashtable resources = YICache.Get(cacheKey) as Hashtable;

     

               if (null == resources)

               {

                  lock (CacheObject)

                  {

                      resources = new Hashtable();

                      LoadResource(resources);//这里假设做一些非常昂贵的IO操作或者其它操作

                      YICache.Max(cacheKey, resources);

                  }

               }

     

               return resources;

           }

    这代码看起来比第一次的好多了。

    但是个假设有两个线程AB同时对GetResource()方法进行访问,哪么AB同时到达lock这一行代码,A先获取锁,然后B只有等待,而当A装载资源完成后,B仍然进行装载资源。

     

    现在对以上代码再进行更改如下:

    public static readonly object CacheObject = new object();

           private static Hashtable GetResource()

           {

               string cacheKey = Type.GetType("ResourceManager").ToString();

               Hashtable resources = YICache.Get(cacheKey) as Hashtable;

     

               if (null == resources)

               {

                  lock (CacheObject)

                  {

                      Hashtable resources = YICache.Get(cacheKey) as Hashtable;

                      if (null == resources)

                      {

                         resources = new Hashtable();

                         LoadResource(resources);//这里假设做一些非常昂贵的IO操作或者其它操作

                         YICache.Max(cacheKey, resources);

                      }

                  }

               }

     

               return resources;

           }

    这样就可以保证在多线程下对一些昂贵的操作进行比较好的控制。

     

    以上的讨论在实现单件设计模式同样存在这个问题

    关于锁的讨论:可以参考11月的MSDN杂志。具体名字忘记了。
  • 相关阅读:
    MongoDB性能优化五步走之读书笔记
    Effective java 第十章 并发 避免过度同步 读书笔记
    Effective java 第三章对于所有对象都通用的方法(一) 读书笔记
    mongodb设计模式策略之读书笔记
    Effective java 第十章 并发 同步访问共享的可变数据 读书笔记
    搬运工生涯开端
    Effective java 第二章创建和销毁对象 读书笔记
    Mongodb聚合操作之读书笔记
    ArcGIS Engine 的插件式开发
    从一个AE画点的例子来看C#QI机制
  • 原文地址:https://www.cnblogs.com/yi/p/679434.html
Copyright © 2011-2022 走看看