zoukankan      html  css  js  c++  java
  • C#实现单例,保证线程安全

    C#中的lock语句是怎么回事,有什么作用?
     
    C#中的lock语句将lock中的语句块视为临界区,让多线程访问临界区代码时,必须顺序访问。他的作用是在多线程环境下,确保临界区中的对象只被一个线程操作,防止出现对象被多次改变情况。
     
    注意的地方有:lock对象必须是一个不可变对象,否则无法阻止另一个线程进入临界区。最好是private static readonly 或者private static。常见的lock (this)、lock (typeof (MyType)) 和 lock ("myLock") 都是不合理的写法。
     
    原因:
    1.lock(this),主要问题是如果类为实例化类,那么this也只是当前实例,不能起到锁定的作用,而且即使是静态类可以被锁定,那么由于尺寸问题,不如锁定不可变小对象合算。
     
    2.lock(typeof())问题在于锁定对象类型当相于锁定类型中的静态对象部分,锁定了所有实例,速度慢;另一方面,有可能程序其他部分在访问该对象,已经替您锁定,将导致您锁定语句的挂起。原文(Here's why: Since there's one type object for all instances of a class, it would appear that locking it would provide a lock equivalent to locking a static object contained in your class. You would lock all instances of the class, wait until other threads were done accessing any part of any instance, then lock access so you could access static members safely and without another thread interfering.)
     
    3.lock("")问题在于微软将内容相同的字符串视为同一个对象,如果您在此锁定了他,那么其实是锁定了同一个对象,将阻止其他地方对字符串的锁定。
     
    lock语句的一个典型应用就是单例模式。 而单例模式的一个最简单实现方式就是用静态对象方式。如下:
    public class ABicycle {   
       private static ABicycle aBicycle = new ABicycle();   
        public ABicycle Instance()   
       {     
          return aBicycle;   
       }
     
    这是实现单例模式最简单的一种方式,但是有一个缺点就是假如ABicycle类被提前调用后,aBicycle即被实例化,没法做到实例化延迟。在此情况下,利用一个关联类可以避免此问题的发生。即:
    public class ABicycle {   
      public ABicycle Instance()   
      {     
          return ABicycleStance.Instance();   
      }
    }
     
    private class ABicycleStance {   
       internal static readonly ABicycle aBicycle = new ABicycle();   
       public ABicycle Instance()   
       {     
          return aBicycle;   
       }
    }
     
    单例模式的一个思路是利用C#的lock语句实现。 最简单实现方式为:
    if(... == null){ ... = new ... } return ...; 
    如果这样实现,有一个问题无法回避,即无法确保只能让一个线程使对象实例化,因为有可能多个线程并发执行到此,同时实例化了对象。为此,需要引用lock语句。引用的方式也有讲究,最直接的实现方式就是:
    private static readonly locker = new object();
    //或者这样写也可以。
    //private static locker = new object();
     
    lock(locker)
    {   
      if(.. == null)   
      {   
         ...   
      }
     
    上面做法可行,但是有一个问题是每次返回时首先要对locker上锁,这样就牺牲了一些本来不必牺牲的性能,因此,可以修改为以下做法:
    private static readonly locker = new object();
     
    if(.. == null)   
    {     
      lock(locker)     
     
      {       
          if(... == null)     
          {
     
          }   
       }
     
    这样,对于多线程来说是安全的,而且不必每次加锁,只有在判断对象没有实例化时加锁,避免了性能上的损失。
  • 相关阅读:
    连接AI与用户,京东云推出视音频通信技术方案
    我身边的高T,问了Java面试者这样的问题......
    解密协议层的攻击——HTTP请求走私
    产业实践推动科技创新,京东科技集团3篇论文入选ICASSP 2021
    2021年人工智能数据采集标注行业四大趋势预测;清华提出深度对齐聚类用于新意图发现
    京东科技集团21篇论文高票入选国际顶会AAAI 2021
    别困惑,不是你的错!90%的开发者把Clubhouse看成了Clickhouse
    京东App Swift 混编及组件化落地
    对话京东科技算法科学家吴友政:回望2020,NLP技术发展速度强劲
    关于京东技术,你想了解的都在这里丨征文活动获奖及优秀专栏推荐
  • 原文地址:https://www.cnblogs.com/dulixiaoqiao/p/6838153.html
Copyright © 2011-2022 走看看