zoukankan      html  css  js  c++  java
  • 13.4 对锁和字段风格的事件的微小改变

    13.4.1 健壮的锁

     1     class Program
     2     {
     3         static object locker = new object();
     4         static void Main(string[] args)
     5         {
     6             List<string> list = new List<string>();
     7             lock (locker)
     8             {
     9                 list.Add("item");
    10             }
    11 
    12             //在C# 4之前——包括使用C# 4处理.NET 4之前的东西时——以上语句将被有效地编译为下面 的代码:
    13 
    14             object tmp = locker;
    15             Monitor.Enter(tmp);
    16             try
    17             {
    18                 list.Add("item");
    19             }
    20             finally
    21             {
    22                 Monitor.Exit(tmp);
    23             }
    24         }
    25     }

    这没有问题,并且它还避免了一些问题。我们要确保释放的监视器与获取的是同一个,因此
    首先将被锁定内容的引用复制到一个临时局部变量内 。这同时意味着锁的表达式只会进行一
    次求值。然后我们在 try 语句块之前获取锁。因此如果获取锁的线程异常终止,则不会执行
    finally 块中释放锁的语句。这还将导致另一个问题:如果线程在获取锁之后和进入 try 块之前
    异常终止,我们也无法释放锁。这可能会导致死锁——其他线程将一直等待该线程释放锁。尽管
    CLR一直以来都在努力阻止类似事情发生,但也不是完全没有可能发生。
    我们所需要的,是一种原子地获取锁并知道它已经被获取的方式。幸运的是,.NET 4新增加
    了 Monitor.Enter 的重载,C# 4的编译器将使用这种方式:

     1     class Program
     2     {
     3         static object locker = new object();
     4         static void Main(string[] args)
     5         {
     6             List<string> list = new List<string>();
     7             object tmp = locker;
     8 
     9             bool acquired = false;
    10             try
    11             {
    12                 Monitor.Enter(tmp, ref acquired);
    13                 list.Add("item");
    14             }
    15             finally
    16             {
    17                 if (acquired)
    18                 {
    19                     Monitor.Exit(tmp);
    20                 }
    21             }
    22         }
    23     }

    13.4.2 字段风格的事件

    值得简单一提的是,C# 4对字段风格事件的实现方式作了两处修改。尽管它们是潜在的破坏性更改,但似乎不会对你产生什么影响。
    总之,字段风格的事件像字段一样进行声明,不再包含显式的 add/remove 语句块,如下:

            public event EventHandler Click;

    首先,线程安全的实现方式发生了改变。在C# 4之前,字段风格的事件生成的代码锁定的是
    this (实例事件)或声明事件的类型(静态事件)。而C# 4中,编译器实现了线程安全,对原子
    的订阅和退订使用了 Interlocked.CompareExchange<T> 。与之前对 lock 语句的修改不同,

    面对旧版本的.NET Framework时,这项更改同样适用。
    其次,在声明事件的类中,事件名称的含义改变了。以前,在声明事件的类中订阅(或退订)
    事件——如 Click += DefaultClickHandler; ——将直接使用后台字段,完全跳过 add/remove
    实现。现在情况变了,使用 += 或 -= 时,事件的名称就指向事件本身,而不再是后台字段。当名
    称用于其他意图时(通常为分配或调用),则仍然指向后台字段。
    尽管在平时使用时你可能不会注意这两处改变,不过它们是合理的,可以使一切变得整洁。
    Chris Burrows在他的博客中深入研究了这个话题,想了解更多内容可以参考http://mng.bz/Kyr4。

  • 相关阅读:
    multiprocessing.Pool报pickling error
    Python 数据库的Connection、Cursor两大对象
    python中的tcp示例详解
    Python网络编程篇之select和epoll
    python select epoll poll的解析
    python网络编程——IO多路复用之epoll
    python实现并发服务器实现方式(多线程/多进程/select/epoll)
    python select模块
    CRM客户关系管理系统(七)
    CRM客户关系管理系统(六)
  • 原文地址:https://www.cnblogs.com/kikyoqiang/p/10116459.html
Copyright © 2011-2022 走看看