zoukankan      html  css  js  c++  java
  • 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%的性能,悲哀呀! 
    采集
  • 相关阅读:
    C++ 虚成员函数和动态联编
    C++ 多态公有继承
    C++ 继承特性
    C++ 公有派生
    C++ 基类与派生类
    C++ 类继承
    C++ 伪私有方法
    C++ new失败
    mysql用户授权
    linux时间设置
  • 原文地址:https://www.cnblogs.com/wwwzzg168/p/4121547.html
Copyright © 2011-2022 走看看