Increased activity in a multi-threaded environment

Starting with .NET 4.0, add / remove event handlers are automatically generated by the stream ( here and here ). Therefore, clients who register their listeners in an open event can do this simultaneously from multiple threads without races.

But what if I want to fire an event in streaming mode? Recommended practice is as follows ( here ):

public event EventHandler MyEvent; protected void OnMyEvent(EventArgs e) { EventHandler myEvent = MyEvent; if (myEvent != null) { myEvent(this, e); } } 

However, after reading something about the .NET memory model (for example, MSDN 2012-12 and 2013-01 ) I no longer think it is correct. My concern is that memory reading might be represented by the compiler, so the code above could be JIT-ted in something like this:

 public event EventHandler MyEvent; protected void OnMyEvent(EventArgs e) { // JIT removed the local variable and introduced two memory reads instead. if (MyEvent != null) { // A race condition may cause the following line to throw a NullReferenceException. MyEvent(this, e); } } 

It is legal to delete a local variable and use repeated reads in memory, since it does not change the behavior of the method if it is executed in the same streaming environment. This is according to the ECMA specification ( ECMA-335: I.12.6.4 ). A clear example is also provided in the MSDN 2013-01 issue .

Am I missing something? If not, please report it.

+4
source share
1 answer

You must add a single line to make the first fragment correct in a multi-threaded environment:

 public event EventHandler MyEvent; protected void OnMyEvent(EventArgs e) { EventHandler myEvent = MyEvent; Thread.MemoryBarrier(); if (myEvent != null) { myEvent(this, e); } } 

Memory prevents read and write reordering for both the compiler and processor. How mutable reads / writes are implemented. Here you can read about the memory barrier .

+2
source

Source: https://habr.com/ru/post/1499504/


All Articles