• C#内部关于绑定事件Event的线程安全


    private EventHandler _FieldsChanged;
    public event EventHandler FieldsChanged
    {
        add
        {
            EventHandler handler2;
            EventHandler fieldsChanged = this._FieldsChanged;
            do
            {
                handler2 = fieldsChanged;
                EventHandler handler3 = (EventHandler)Delegate.Combine(handler2, value);
                fieldsChanged = Interlocked.CompareExchange<EventHandler>(ref this._FieldsChanged, handler3, handler2);
            }
            while (fieldsChanged != handler2);
        }
        remove
        {
            EventHandler handler2;
            EventHandler fieldsChanged = this._FieldsChanged;
            do
            {
                handler2 = fieldsChanged;
                EventHandler handler3 = (EventHandler)Delegate.Remove(handler2, value);
                fieldsChanged = Interlocked.CompareExchange<EventHandler>(ref this._FieldsChanged, handler3, handler2);
            }
            while (fieldsChanged != handler2);
        }
    }
        下面是我最后的理解,也许是错的:
    EventHandler handler2;
    EventHandler fieldsChanged = this._FieldsChanged;
    do
    {
        // 两个本地变量都保存着_FieldsChanged的本地引用
        handler2 = fieldsChanged;
        // 事件绑定。这是唯一一句业务代码
        EventHandler handler3 = (EventHandler)Delegate.Combine(handler2, value);
        // 如果_FieldsChanged等于handler2,就执行_FieldsChanged=handler3,这里是原子操作,线程安全
        // 如果不等,很明显,有线程冲突存在,数据被别的线程修改过了,这里返回_FieldsChanged到fieldsChanged中去
        fieldsChanged = Interlocked.CompareExchange<EventHandler>(ref this._FieldsChanged, handler3, handler2);
    }
    while (fieldsChanged != handler2);

    // 实际上,整个过程,如果不考虑线程安全,可以直接这么写
    _FieldsChanged = (EventHandler)Delegate.Combine(_FieldsChanged, value);
    // 这段代码的精妙之处就在于这个线程安全,如果Combine后,别的线程也进来,那就出现了数据丢失
    // 当然,常规做法可以是Lock住这段代码,但是,线程冲突的可行性不到1%,为此损失了99%的性能,悲哀呀! 
    采集
  • 相关阅读:
    算法基础_递归_求杨辉三角第m行第n个数字
    算法基础_递归_返回字符串的反串
    算法基础_递归_求两个字符串的公共最长子序列长度
    算法基础_递归_全排列问题
    玩转数据结构:第7章 集合和映射
    Java8 新特性_Stream API
    一、VIP课程:互联网工程专题 04-Maven私服使用与插件开发
    Java8 新特性_Lambda 表达式
    一、VIP课程:互联网工程专题 03-Maven基本概念与核心配置
    玩转数据结构:第6章 二分搜索树
  • 原文地址:https://www.cnblogs.com/wwwzzg168/p/4121547.html
Copyright © 2020-2023  润新知