C # event thread security,

Source: Internet
Author: User

C # event thread security,

I suddenly thought about thread security when using the event feature in C #. In the past, although there was a "copy reference + null judgment" pattern (blindly ), however, I did not have any in-depth understanding or thinking.

I have further understood the materials and experiments.

 

General event usage mode

Field-like event ):

public event EventHandler Done;

Class raise:

protected void OnDone(){    var done = Done;    if (done != null)    {        done(this, new EventArgs());    }}

You can't help wondering why we need to copy the reference? How is multithreading?

 

How the compiler implements event in C #3.0 and C #4.0

To solve the above questions, I checked some information, including a blog post from the C # compiler development team member Field-like Events Considered Harmful.

This blog post describes how the compiler implements field-like event (also the most common usage) in C #3.0.

 

For such code,

class EventInCS3{    public event EventHandler Done;}

The compiler converts it:

class EventInCS3{    private EventHandler __Done; // 1    public event EventHandler Done    {        add        {            lock (this) // 2            {                __Done = __Done + value; // 3            }        }        remove        {            lock (this) { __Done = __Done - value; }        }    }}

Note the following ):

1. The real delegate chain hidden under the event. We actually use the subclass MulticastDelegate (refer to the open-source coreclr implementation ).

3. just as the + and-operators play a combination of strings for the string type, the delegate type also plays a combination of two chains (refer to MSDN). In fact, Delegate is called. combine and Delegate. remove. It also introduces the classic thread problem (the modification is lost ).

2. To solve the multithreading problem, lock is used.

(Leave this lock (this) alone. Of course, as mentioned in the above blog post, the compiler does not use lock, and then uses the static method of Monitor to synchronize, but is implemented through IL (MethodImplAttribute (MethodImplOptions. Synchronized. These are not recommended by C # itself .)

 

In C #4.0, the implementation of synchronization has changed. For more information, see this blog post by the same author two years later.

The default add and remove implementations of the compiler use compare and swap to implement lock-free synchronization. It is worth noting that,Delegate is an unchangeable type., That is, + =,-=, will point to a new object, instead of the original object (similar to string ).

You can view the add_Done and remove_Done generated in the Assembly by using IL. The following code is generated:

static void add_Done(EventHandler value){    EventHandler V_0 = __Done;    EventHandler V_1, V_2;    do    {        V_1 = V_0;        V_2 = (EventHandler)Delegate.Combine(V_1, value);        V_0 = Interlocked.CompareExchange<EventHandler>(ref __Done, V_2, V_1);    } while (V_0 != V_1);}

 

C # sorting event-related semantic changes in 4.0

In another blog post by the same author, we introduced event-related semantic changes in C #4.0, mainly+ =,-= Operator semantic change.

 

In C #3.0, if an event is accessed outside of this class, it is considered to be accessed by the event itself, for example, we know that we can only use the + = and-= operators to access (that is, call the corresponding add and remove accessors). Inside the class, all accesses to this event will be considered as the delegate implemented by the event (access to Done, actually access _ Done ).

In this way, we can copy the reference in the OnDone method, judge null, and call it. In this case, the Done identifier represents a reference to an EventHandler object.

This is also the problem with C #3.0. In this case, we will write down

Done += SomeHandlerMethod;

+ = Actually called:

EventHandler EventHandler.operator +(EventHandler left, EventHandler right)

Write a normal, non-event EventHandler ++ = operation in Visual Studio 2015. When you place the cursor over ++ =, the function signature is displayed. In C #3.0, even the event is handled.

As a result, the synchronization function provided by the default add accessors is lost..

 

This phenomenon has been improved in C #4.0. When you access the identifier of the event within the class, the + =,-= operators are considered to be the add and remove calls.

We can see that when C #4.0 writes the same code, the signature of the + = call is:

void EventInCS4.Done.add 

 

Custom event accessors

When customizing the event (non-field-like event), The add and remove accessors compiled by ourselves will not be synchronized by default. To ensure thread security, manually add synchronization (such as lock (someLockObject )).

In this case, the access event identifier within the class will only be treated as the access event itself. To trigger an event (Done), you need to access the corresponding delegate (_ Done (this, new EventArgs ())).

 

The correct method for event operation

Generally, you do not need to implement the event by yourself. Simply use field-like.

Whether you access the delegate (field-like event) through the event identifier or directly access the delegate (Custom event), we get a reference to the delegate object, in addition, the delegate object cannot be modified.The referenced replication is atomic.. Therefore, we can copy the delegate reference at will, judge null, and invoke.

 

Some code snippet such:

 

Appendix

I have no in-depth understanding about whether the compiler will optimize the replication reference as a repeated local variable, so that in some cases, the following methods need to be used.

Interlocked.CompareExchange(ref Done, null, null);

After a simple query, I learned that Microsoft's own CLR does not need to care about this issue. It covers its strictly-compliant memory model and does not introduce new read operations. However, in other casesPossibleThis problem exists. Links to related articles and discussions are as follows:

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.