not*_*ama 5 c# multithreading thread-safety
具体来说,“+=”操作是原子的吗?如果我使用“事件”关键字,或者只是一个普通的旧委托,这有什么不同吗?
对于大多数类型,它是读取,然后是“+”运算符,然后是写入。所以,它不是原子的。我想知道代表/活动是否有特殊情况。
这种代码是必要的还是多余的:
Action handler;
object lockObj;
public event Action Handler {
add { lock(lockObj) { handler += value; } }
remove { lock(lockObj) { handler -= value; } }
}
Run Code Online (Sandbox Code Playgroud)
是的,自动实现的事件上的+=和运算符是原子的(如果库使用自定义事件处理程序,它很容易不是原子的)。摘自 MSDN 杂志文章.NET Matters:事件访问器-=
\n\n当 C# 编译器为 MyClass 生成代码时,输出\n Microsoft\xc2\xae 中间语言 (MSIL) 的行为与使用图 1 中的代码生成的输出相同。
\n\n图 1 扩展事件实现
\n\nRun Code Online (Sandbox Code Playgroud)\n\nclass MyClass\n{\n private EventHandler _myEvent;\n\n public event EventHandler MyEvent\n {\n [MethodImpl(MethodImplOptions.Synchronized)]\n add \n { \n _myEvent = (EventHandler)Delegate.Combine(_myEvent, value);\n }\n [MethodImpl(MethodImplOptions.Synchronized)]\n remove \n { \n _myEvent = (EventHandler)Delegate.Remove(_myEvent, value); \n }\n }\n ...\n}\n[...]
\n\n显式事件实现的另一个用途是提供自定义同步机制(或删除同步机制)。您会在图 1 中注意到,添加和删除访问器都使用 MethodImplAttribute 进行修饰,该属性指定访问器应该同步。对于实例事件,此属性相当于用当前实例上的锁包装每个访问器的内容:
\n\nRun Code Online (Sandbox Code Playgroud)\nadd { lock(this) _myEvent += value; } \nremove { lock(this) _myEvent -= value; }\n