Is there a race condition in this common pattern used to prevent NullReferenceException?

前端 未结 2 669
我在风中等你
我在风中等你 2020-12-15 17:46

I asked this question and got this interesting (and a little disconcerting) answer.

Daniel states in his answer (unless I\'m readin

2条回答
  •  猫巷女王i
    2020-12-15 18:01

    In CLR via C# (pp. 264–265), Jeffrey Richter discusses this specific problem, and acknowledges that it is possible for the local variable to be swapped out:

    [T]his code could be optimized by the compiler to remove the local […] variable entirely. If this happens, this version of the code is identical to the [version that references the event/callback directly twice], so a NullReferenceException is still possible.

    Richter suggests the use of Interlocked.CompareExchange to definitively resolve this issue:

    public void DoCallback() 
    {
        Action local = Interlocked.CompareExchange(ref _Callback, null, null);
        if (local != null)
            local();
    }
    

    However, Richter acknowledges that Microsoft’s just-in-time (JIT) compiler does not optimize away the local variable; and, although this could, in theory, change, it almost certainly never will because it would cause too many applications to break as a result.

    This question has already been asked and answered at length in “Allowed C# Compiler optimization on local variables and refetching value from memory”. Make sure to read the answer by xanatox and the “Understand the Impact of Low-Lock Techniques in Multithreaded Apps” article it cites. Since you asked specifically about Mono, you should pay attention to referenced “[Mono-dev] Memory Model?” mailing list message:

    Right now we provide loose semantics close to ecma backed by the architecture you're running.

提交回复
热议问题