"对易变场的引用不会被视为不稳定的"含义

Jad*_*ias 42 .net c# multithreading volatile

以下代码

using System.Threading;

class Test
{
    volatile int counter = 0;
    public void Increment()
    {
        Interlocked.Increment(ref counter);
    }
}
Run Code Online (Sandbox Code Playgroud)

引发以下编译器警告:

"A reference to a volatile field will not be treated as volatile"
Run Code Online (Sandbox Code Playgroud)

我在这里做错了什么来提出这个警告?为什么编译器会对此发出警告?

Dar*_*rov 45

你没有做错任何事.根据文件:

通常不应使用ref或out参数传递volatile字段,因为它不会在函数范围内被视为volatile.这有例外,例如调用互锁API时.

  • 我会说Interlocked方法仍然没有区别对待它们如何对待任何其他领域 - 它只是*所有*字段由Interlocked以特殊方式处理. (18认同)
  • 同意.易失性与Interlocked API无关.但在某些情况下,将Interlocked和volatile混合起来非常有用. (3认同)

Jon*_*eet 31

基本上警告是,当您通过引用传递volatile字段时,调用代码不知道以易失性方式处理它.对于可能无关紧要的Interlocked.Increment,由于方法的性质 - 但是如果您使用Interlocked ,无论如何都不需要变量.

一般来说,我想我会避免将两者混合在一起 - 如果你使用的是Interlocked,那么到处都是(使用Interlocked.CompareExchange(ref counter, 0, 0)它来阅读).我不能说我个人经常使用volatile.对于简单的计数器,我可能会使用Interlocked,但我更可能使用锁来执行大多数任务.

  • Interlocked可以做出正确的一切 - 记忆障碍,原子性等.没有它,它将毫无用处. (3认同)

Rob*_*ser 30

用这个:

        #pragma warning disable 420
        //                       M
        //                      dM
        //                      MMr
        //                     4MMML                  .
        //                     MMMMM.                xf
        //     .              "MMMMM               .MM-
        //      Mh..          +MMMMMM            .MMMM
        //      .MMM.         .MMMMML.          MMMMMh
        //       )MMMh.        MMMMMM         MMMMMMM
        //        3MMMMx.     'MMMMMMf      xnMMMMMM"
        //        '*MMMMM      MMMMMM.     nMMMMMMP"
        //          *MMMMMx    "MMMMM\    .MMMMMMM=
        //           *MMMMMh   "MMMMM"   JMMMMMMP
        //             MMMMMM   3MMMM.  dMMMMMM            .
        //              MMMMMM  "MMMM  .MMMMM(        .nnMP"
        //  =..          *MMMMx  MMM"  dMMMM"    .nnMMMMM*
        //    "MMn...     'MMMMr 'MM   MMM"   .nMMMMMMM*"
        //     "4MMMMnn..   *MMM  MM  MMP"  .dMMMMMMM""
        //       ^MMMMMMMMx.  *ML "M .M*  .MMMMMM**"
        //          *PMMMMMMhn. *x > M  .MMMM**""
        //             ""**MMMMhx/.h/ .=*"
        //                      .3P"%....
        //                    nP"     "*MMnx
        if(Interlocked.CompareExchange(ref isLoaded, 1, 0) != 0)
            return;
        #pragma warning restore 420
Run Code Online (Sandbox Code Playgroud)

  • 很好的ascii艺术品,但它没有回答这个问题 (12认同)
  • 但是一旦你理解了其他答案,它确实会派上用场,如果你决定同时使用Interlocked和volatile. (4认同)
  • @JaderDias - 不,但它会告诉你如何处理警告.这是非常有用的. - 此外,艺术品也很有趣. (3认同)