When is "volatile" used instead of "lock" ?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Samuel R. Neff

    When is "volatile" used instead of "lock" ?


    When is it appropriate to use "volatile" keyword? The docs simply
    state:

    "
    The volatile modifier is usually used for a field that is accessed by
    multiple threads without using the lock Statement (C# Reference)
    statement to serialize access.
    "

    But when is it better to use "volatile" instead of "lock" ?

    Thanks,

    Sam

    ------------------------------------------------------------
    We're hiring! B-Line Medical is seeking .NET
    Developers for exciting positions in medical product
    development in MD/DC. Work with a variety of technologies
    in a relaxed team environment. See ads on Dice.com.


  • ben.biddington@gmail.com

    #2
    Re: When is "volatile& quot; used instead of "lock&quot ; ?

    On May 21, 3:35 pm, Samuel R. Neff <samueln...@nom ail.comwrote:
    When is it appropriate to use "volatile" keyword? The docs simply
    state:
    >
    "
    The volatile modifier is usually used for a field that is accessed by
    multiple threads without using the lock Statement (C# Reference)
    statement to serialize access.
    "
    >
    But when is it better to use "volatile" instead of "lock" ?
    >
    Thanks,
    >
    Sam
    >
    ------------------------------------------------------------
    We're hiring! B-Line Medical is seeking .NET
    Developers for exciting positions in medical product
    development in MD/DC. Work with a variety of technologies
    in a relaxed team environment. See ads on Dice.com.
    You can also the System.Threadin g.Interlocked class which maintains
    volatile semantics.

    Seealso: http://www.albahari.com/threading/part4.html

    Comment

    • Christof Nordiek

      #3
      Re: When is &quot;volatile& quot; used instead of &quot;lock&quot ; ?

      "Samuel R. Neff" <samuelneff@nom ail.comschrieb im Newsbeitrag
      news:ecb3531i9o 3ekhp7tlt69icaq g52fumst6@4ax.c om...
      >
      When is it appropriate to use "volatile" keyword? The docs simply
      state:
      >
      "
      The volatile modifier is usually used for a field that is accessed by
      multiple threads without using the lock Statement (C# Reference)
      statement to serialize access.
      "
      >
      For a volatile field the reodering of the memory access by the optimizer is
      restricted.
      A write to a volatile field is always done after all other memory accesses
      which precede in the instruction sequence.
      A read from a volatile field is always done before all other memory accesses
      wich occur after it in the instruction sequence.

      A volatile field as a simple way to flag, that memorymanipulat ions are over.

      following an example from the specs:

      using System;
      using System.Threadin g;
      class Test
      {
      public static int result;
      public static volatile bool finished;
      static void Thread2() {
      result = 143;
      finished = true;
      }

      static void Main() {
      finished = false;
      // Run Thread2() in a new thread
      new Thread(new ThreadStart(Thr ead2)).Start();
      // Wait for Thread2 to signal that it has a result by setting
      // finished to true.
      for (;;) {
      if (finished) {
      Console.WriteLi ne("result = {0}", result);
      return;
      }
      }
      }
      }

      Since finished is volatile, in method Thread2 the write to result will
      allways occur before the write to finished and in method Main the read from
      finished will allways occur before the read from result, so the read from
      result in Main can't occur before the write in Thread2.

      HTH

      Christof


      Comment

      • james.curran@gmail.com

        #4
        Re: When is &quot;volatile& quot; used instead of &quot;lock&quot ; ?

        On May 21, 10:35 am, Samuel R. Neff <samueln...@nom ail.comwrote:
        When is it appropriate to use "volatile" keyword? The docs simply
        state:
        Often, if just one thread is writing to the object (and other
        threads just reading it),you can get away with using just volatile.

        Generally, the shared object would need to be an atomic value, so the
        reader may see it sudden change from state A to state B, but would
        never see it half-way between A & B.

        Comment

        • Jon Skeet [C# MVP]

          #5
          Re: When is &quot;volatile& quot; used instead of &quot;lock&quot ; ?

          ben.biddington@ gmail.com <ben.biddington @gmail.comwrote :
          You can also the System.Threadin g.Interlocked class which maintains
          volatile semantics.
          >
          Seealso: http://www.albahari.com/threading/part4.html
          But only if you use it for both the writing *and* the reading, which
          isn't terribly obvious from the docs.

          --
          Jon Skeet - <skeet@pobox.co m>
          http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
          If replying to the group, please do not mail me too

          Comment

          • Brian Gideon

            #6
            Re: When is &quot;volatile& quot; used instead of &quot;lock&quot ; ?

            On May 21, 10:58 am, "Christof Nordiek" <c...@nospam.de wrote:
            For a volatile field the reodering of the memory access by the optimizer is
            restricted.
            A write to a volatile field is always done after all other memory accesses
            which precede in the instruction sequence.
            A read from a volatile field is always done before all other memory accesses
            wich occur after it in the instruction sequence.
            >
            A volatile field as a simple way to flag, that memorymanipulat ions are over.
            >
            following an example from the specs:
            >
            using System;
            using System.Threadin g;
            class Test
            {
            public static int result;
            public static volatile bool finished;
            static void Thread2() {
            result = 143;
            finished = true;
            }
            >
            static void Main() {
            finished = false;
            // Run Thread2() in a new thread
            new Thread(new ThreadStart(Thr ead2)).Start();
            // Wait for Thread2 to signal that it has a result by setting
            // finished to true.
            for (;;) {
            if (finished) {
            Console.WriteLi ne("result = {0}", result);
            return;
            }
            }
            }
            >
            }
            >
            Since finished is volatile, in method Thread2 the write to result will
            allways occur before the write to finished and in method Main the read from
            finished will allways occur before the read from result, so the read from
            result in Main can't occur before the write in Thread2.
            >
            HTH
            >
            Christof
            One other important behavior that is demonstrated in your example is
            that it guarentees that writes to finished are seen from other
            threads. That prevents the infinite loop in Main().

            Brian

            Comment

            • Chris Mullins [MVP]

              #7
              Re: When is &quot;volatile& quot; used instead of &quot;lock&quot ; ?

              "Samuel R. Neff" <samuelneff@nom ail.comwrote:
              When is it appropriate to use "volatile" keyword? The docs simply
              state:
              "The volatile modifier is usually used for a field that is accessed by
              multiple threads without using the lock Statement (C# Reference)
              statement to serialize access. "
              >
              But when is it better to use "volatile" instead of "lock" ?
              I would recommend using locks and properties, rather than volatile variables
              or Interlocked Methods.

              Locking is easier and more straight forward, and has fewer subtle issues,
              than do the other two methods.

              --
              Chris Mullins, MCSD.NET, MCPD:Enterprise , Microsoft C# MVP



              Comment

              • Ben Voigt

                #8
                Re: When is &quot;volatile& quot; used instead of &quot;lock&quot ; ?


                <ben.biddington @gmail.comwrote in message
                news:1179761300 .206885.51230@z 28g2000prd.goog legroups.com...
                On May 21, 3:35 pm, Samuel R. Neff <samueln...@nom ail.comwrote:
                >When is it appropriate to use "volatile" keyword? The docs simply
                >state:
                >>
                >"
                >The volatile modifier is usually used for a field that is accessed by
                >multiple threads without using the lock Statement (C# Reference)
                >statement to serialize access.
                >"
                >>
                >But when is it better to use "volatile" instead of "lock" ?
                >>
                >Thanks,
                >>
                >Sam
                >>
                >------------------------------------------------------------
                >We're hiring! B-Line Medical is seeking .NET
                >Developers for exciting positions in medical product
                >development in MD/DC. Work with a variety of technologies
                >in a relaxed team environment. See ads on Dice.com.
                >
                You can also the System.Threadin g.Interlocked class which maintains
                volatile semantics.
                You should use volatile and Interlocked together, neither fully replaces the
                other.

                Comment

                • Willy Denoyette [MVP]

                  #9
                  Re: When is &quot;volatile& quot; used instead of &quot;lock&quot ; ?

                  "Ben Voigt" <rbv@nospam.nos pamwrote in message
                  news:uln5JOMnHH A.3968@TK2MSFTN GP06.phx.gbl...
                  >
                  <ben.biddington @gmail.comwrote in message
                  news:1179761300 .206885.51230@z 28g2000prd.goog legroups.com...
                  >On May 21, 3:35 pm, Samuel R. Neff <samueln...@nom ail.comwrote:
                  >>When is it appropriate to use "volatile" keyword? The docs simply
                  >>state:
                  >>>
                  >>"
                  >>The volatile modifier is usually used for a field that is accessed by
                  >>multiple threads without using the lock Statement (C# Reference)
                  >>statement to serialize access.
                  >>"
                  >>>
                  >>But when is it better to use "volatile" instead of "lock" ?
                  >>>
                  >>Thanks,
                  >>>
                  >>Sam
                  >>>
                  >>------------------------------------------------------------
                  >>We're hiring! B-Line Medical is seeking .NET
                  >>Developers for exciting positions in medical product
                  >>development in MD/DC. Work with a variety of technologies
                  >>in a relaxed team environment. See ads on Dice.com.
                  >>
                  >You can also the System.Threadin g.Interlocked class which maintains
                  >volatile semantics.
                  >
                  You should use volatile and Interlocked together, neither fully replaces
                  the other.
                  >
                  Not necessarily, there is no need for volatile, as long you Interlock
                  consistently across all threads in the process. This means that once you
                  access a shared variable using Interlock, all threads should use Interlock.

                  Willy.

                  Comment

                  • Ben Voigt

                    #10
                    Re: When is &quot;volatile& quot; used instead of &quot;lock&quot ; ?


                    "Willy Denoyette [MVP]" <willy.denoyett e@telenet.bewro te in message
                    news:1B1A6E75-67F7-4B6E-B858-C7517C5BEA43@mi crosoft.com...
                    "Ben Voigt" <rbv@nospam.nos pamwrote in message
                    news:uln5JOMnHH A.3968@TK2MSFTN GP06.phx.gbl...
                    >>
                    ><ben.biddingto n@gmail.comwrot e in message
                    >news:117976130 0.206885.51230@ z28g2000prd.goo glegroups.com.. .
                    >>On May 21, 3:35 pm, Samuel R. Neff <samueln...@nom ail.comwrote:
                    >>>When is it appropriate to use "volatile" keyword? The docs simply
                    >>>state:
                    >>>>
                    >>>"
                    >>>The volatile modifier is usually used for a field that is accessed by
                    >>>multiple threads without using the lock Statement (C# Reference)
                    >>>statement to serialize access.
                    >>>"
                    >>>>
                    >>>But when is it better to use "volatile" instead of "lock" ?
                    >>>>
                    >>>Thanks,
                    >>>>
                    >>>Sam
                    >>>>
                    >>>------------------------------------------------------------
                    >>>We're hiring! B-Line Medical is seeking .NET
                    >>>Developers for exciting positions in medical product
                    >>>developmen t in MD/DC. Work with a variety of technologies
                    >>>in a relaxed team environment. See ads on Dice.com.
                    >>>
                    >>You can also the System.Threadin g.Interlocked class which maintains
                    >>volatile semantics.
                    >>
                    >You should use volatile and Interlocked together, neither fully replaces
                    >the other.
                    >>
                    >
                    Not necessarily, there is no need for volatile, as long you Interlock
                    consistently across all threads in the process. This means that once you
                    access a shared variable using Interlock, all threads should use
                    Interlock.
                    I don't think so, actually. Without volatile semantics, the compiler is
                    free to cache the value of any parameter, including in/out parameters. Say
                    you are calling an Interlocked method in a loop. If the variable is not
                    volatile, the compiler can actually call Interlocked on a local copy, and
                    then write the value to the real variable once, at the end of the loop (and
                    worse, it can do so in a non-atomic way). Anything that maintains correct
                    operation from the perspective of the calling thread is permissible for
                    non-volatile variable access. Why would a compiler do this? For optimal
                    use of cache. By using a local copy of a variable passed byref, locality of
                    reference is improved, and additionally, a thread's stack (almost) never
                    incurs cache coherency costs.

                    Note that this is not a problem for pass-by-pointer, which must use the true
                    address of the referenced variable in order to enable pointer arithmetic.
                    But pointer arithmetic isn't allowed for tracking handles, a handle is an
                    opaque value anyway.

                    For lockless data structures, always use volatile. And then stick that
                    volatile variable close in memory to what it is protecting, because CPU
                    cache has to load and flush an entire cache line at once, and volatile write
                    semantics require flushing all pending writes.
                    >
                    Willy.
                    >

                    Comment

                    • Jon Skeet [C# MVP]

                      #11
                      Re: When is &quot;volatile& quot; used instead of &quot;lock&quot ; ?

                      Ben Voigt <rbv@nospam.nos pamwrote:
                      Not necessarily, there is no need for volatile, as long you Interlock
                      consistently across all threads in the process. This means that once you
                      access a shared variable using Interlock, all threads should use
                      Interlock.
                      >
                      I don't think so, actually. Without volatile semantics, the compiler is
                      free to cache the value of any parameter, including in/out parameters. Say
                      you are calling an Interlocked method in a loop. If the variable is not
                      volatile, the compiler can actually call Interlocked on a local copy, and
                      then write the value to the real variable once, at the end of the loop (and
                      worse, it can do so in a non-atomic way).
                      No - the CLI spec *particularly* mentions Interlocked operations, and
                      that they perform implicit acquire/release operations. In other words,
                      the JIT can't move stuff around in this particular case. Interlocked
                      would be pretty pointless without this.

                      --
                      Jon Skeet - <skeet@pobox.co m>
                      http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
                      If replying to the group, please do not mail me too

                      Comment

                      • Willy Denoyette [MVP]

                        #12
                        Re: When is &quot;volatile& quot; used instead of &quot;lock&quot ; ?

                        "Ben Voigt" <rbv@nospam.nos pamwrote in message
                        news:uXg8juTnHH A.2296@TK2MSFTN GP03.phx.gbl...
                        >
                        "Willy Denoyette [MVP]" <willy.denoyett e@telenet.bewro te in message
                        news:1B1A6E75-67F7-4B6E-B858-C7517C5BEA43@mi crosoft.com...
                        >"Ben Voigt" <rbv@nospam.nos pamwrote in message
                        >news:uln5JOMnH HA.3968@TK2MSFT NGP06.phx.gbl.. .
                        >>>
                        >><ben.biddingt on@gmail.comwro te in message
                        >>news:11797613 00.206885.51230 @z28g2000prd.go oglegroups.com. ..
                        >>>On May 21, 3:35 pm, Samuel R. Neff <samueln...@nom ail.comwrote:
                        >>>>When is it appropriate to use "volatile" keyword? The docs simply
                        >>>>state:
                        >>>>>
                        >>>>"
                        >>>>The volatile modifier is usually used for a field that is accessed by
                        >>>>multiple threads without using the lock Statement (C# Reference)
                        >>>>statement to serialize access.
                        >>>>"
                        >>>>>
                        >>>>But when is it better to use "volatile" instead of "lock" ?
                        >>>>>
                        >>>>Thanks,
                        >>>>>
                        >>>>Sam
                        >>>>>
                        >>>>------------------------------------------------------------
                        >>>>We're hiring! B-Line Medical is seeking .NET
                        >>>>Developer s for exciting positions in medical product
                        >>>>developme nt in MD/DC. Work with a variety of technologies
                        >>>>in a relaxed team environment. See ads on Dice.com.
                        >>>>
                        >>>You can also the System.Threadin g.Interlocked class which maintains
                        >>>volatile semantics.
                        >>>
                        >>You should use volatile and Interlocked together, neither fully replaces
                        >>the other.
                        >>>
                        >>
                        >Not necessarily, there is no need for volatile, as long you Interlock
                        >consistently across all threads in the process. This means that once you
                        >access a shared variable using Interlock, all threads should use
                        >Interlock.
                        >
                        I don't think so, actually. Without volatile semantics, the compiler is
                        free to cache the value of any parameter, including in/out parameters.
                        Say you are calling an Interlocked method in a loop. If the variable is
                        not volatile, the compiler can actually call Interlocked on a local copy,
                        and then write the value to the real variable once, at the end of the loop
                        (and worse, it can do so in a non-atomic way). Anything that maintains
                        correct operation from the perspective of the calling thread is
                        permissible for non-volatile variable access. Why would a compiler do
                        this? For optimal use of cache. By using a local copy of a variable
                        passed byref, locality of reference is improved, and additionally, a
                        thread's stack (almost) never incurs cache coherency costs.
                        >
                        Note that this is not a problem for pass-by-pointer, which must use the
                        true address of the referenced variable in order to enable pointer
                        arithmetic. But pointer arithmetic isn't allowed for tracking handles, a
                        handle is an opaque value anyway.
                        >
                        For lockless data structures, always use volatile. And then stick that
                        volatile variable close in memory to what it is protecting, because CPU
                        cache has to load and flush an entire cache line at once, and volatile
                        write semantics require flushing all pending writes.
                        >
                        >>
                        >Willy.
                        >>
                        >
                        >


                        No, not at all. Interlocked operations imply a full fence, that is, reads
                        have acquire and writes have release semantics. That means that the JIT may
                        not register these variables nor store them locally and cannot move stuff
                        around them.
                        Think of this, what would be the use of Interlocked operation when used in
                        languages that don't support volatile (like VB.NET) or good old C/C++
                        (except VC7 and up).
                        I also don't agree with your statement that you should *always* use volatile
                        in lock free or low lock scenario's. IMO, you should almost never use
                        volatile, unless you perfectly understand the semantics of the memory model
                        of the CLR/CLI (ECMA differs from V1.X differs from V2 for instance) and the
                        memory model of the CPU (IA32 vs. IA64). The last year I was involved in the
                        resolution of a number of nasty bugs , all of them where the result of
                        people trying to out-smart the system by applying lock free or low lock
                        techniques using volatile, since then whenever I see volatile I'm getting
                        very suspicious, really.......


                        Willy.


                        Comment

                        • Barry Kelly

                          #13
                          Re: When is &quot;volatile& quot; used instead of &quot;lock&quot ; ?

                          Willy Denoyette [MVP] wrote:
                          I also don't agree with your statement that you should *always* use volatile
                          in lock free or low lock scenario's.
                          As far as I can see from the rest of your post, I think you've made a
                          mis-statement here. I think what you mean to say is that you shouldn't
                          use lock-free or low-locking unless there's no alternative, not that
                          volatile shouldn't be used - because volatile is usually very necessary
                          in order to get memory barriers right in those circumstances.
                          IMO, you should almost never use
                          volatile, unless you perfectly understand the semantics of the memory model
                          of the CLR/CLI (ECMA differs from V1.X differs from V2 for instance) and the
                          memory model of the CPU (IA32 vs. IA64). The last year I was involved in the
                          resolution of a number of nasty bugs , all of them where the result of
                          people trying to out-smart the system by applying lock free or low lock
                          techniques using volatile, since then whenever I see volatile I'm getting
                          very suspicious, really.......
                          I agree with you about seeing 'volatile' and it raising red flags, but
                          the cure is to use proper locking if possible, and careful reasoning
                          (rather than shotgun 'volatile' and guesswork), rather than simply
                          omitting 'volatile'.

                          -- Barry

                          --

                          Comment

                          • Willy Denoyette [MVP]

                            #14
                            Re: When is &quot;volatile& quot; used instead of &quot;lock&quot ; ?

                            "Barry Kelly" <barry.j.kelly@ gmail.comwrote in message
                            news:bea953lm6m qnu24mrik16j89b 1oprglgpo@4ax.c om...
                            Willy Denoyette [MVP] wrote:
                            >
                            >I also don't agree with your statement that you should *always* use
                            >volatile
                            >in lock free or low lock scenario's.
                            >
                            As far as I can see from the rest of your post, I think you've made a
                            mis-statement here. I think what you mean to say is that you shouldn't
                            use lock-free or low-locking unless there's no alternative, not that
                            volatile shouldn't be used - because volatile is usually very necessary
                            in order to get memory barriers right in those circumstances.
                            >
                            >IMO, you should almost never use
                            >volatile, unless you perfectly understand the semantics of the memory
                            >model
                            >of the CLR/CLI (ECMA differs from V1.X differs from V2 for instance) and
                            >the
                            >memory model of the CPU (IA32 vs. IA64). The last year I was involved in
                            >the
                            >resolution of a number of nasty bugs , all of them where the result of
                            >people trying to out-smart the system by applying lock free or low lock
                            >techniques using volatile, since then whenever I see volatile I'm getting
                            >very suspicious, really.......
                            >
                            I agree with you about seeing 'volatile' and it raising red flags, but
                            the cure is to use proper locking if possible, and careful reasoning
                            (rather than shotgun 'volatile' and guesswork), rather than simply
                            omitting 'volatile'.
                            >
                            Well, I wasn't suggesting to omit 'volatile, sorry hif I gave this
                            impression. What I meant was, that you should be very if when looking for
                            lock-free or low locking alternatives, and if you do, that you should not
                            "always" use volatile.
                            Note that there are alternatives to volatile fields, there are
                            Thread.MemoryBa rrier, Thread.Volatile Read, Thread.Volatile Write and the
                            Interlocked API's, and these alternatives have IMO the (slight) advantages
                            that they "forces" developers to reason about their usage, something which
                            is less the case (from what I've learned when talking with other devs.
                            across several teams) with volatile.
                            But here also, you need to be very careful, (the red flag should be raised
                            whenever you see any of these too). You need to reason about their usage and
                            that's the major problem when writing threaded code, even experienced
                            developer have a hard time when reasoning about multithreading using locks,
                            programming models that require to reason about how and when to use explicit
                            fences or barriers are IMO too difficult, even for experts, to use reliably
                            in mainstream computing, and this is what .NET is all about isn't it?.

                            Willy.


                            Willy.

                            Comment

                            • Ben Voigt

                              #15
                              Re: When is &quot;volatile& quot; used instead of &quot;lock&quot ; ?


                              "Willy Denoyette [MVP]" <willy.denoyett e@telenet.bewro te in message
                              news:BFF370C9-379B-4B12-A00F-CF8195C64E1E@mi crosoft.com...
                              "Ben Voigt" <rbv@nospam.nos pamwrote in message
                              news:uXg8juTnHH A.2296@TK2MSFTN GP03.phx.gbl...
                              >>
                              >"Willy Denoyette [MVP]" <willy.denoyett e@telenet.bewro te in message
                              >news:1B1A6E7 5-67F7-4B6E-B858-C7517C5BEA43@mi crosoft.com...
                              >>"Ben Voigt" <rbv@nospam.nos pamwrote in message
                              >>news:uln5JOMn HHA.3968@TK2MSF TNGP06.phx.gbl. ..
                              >>>>
                              >>><ben.bidding ton@gmail.comwr ote in message
                              >>>news:1179761 300.206885.5123 0@z28g2000prd.g ooglegroups.com ...
                              >>>>On May 21, 3:35 pm, Samuel R. Neff <samueln...@nom ail.comwrote:
                              >>>>>When is it appropriate to use "volatile" keyword? The docs simply
                              >>>>>state:
                              >>>>>>
                              >>>>>"
                              >>>>>The volatile modifier is usually used for a field that is accessed by
                              >>>>>multiple threads without using the lock Statement (C# Reference)
                              >>>>>statemen t to serialize access.
                              >>>>>"
                              >>>>>>
                              >>>>>But when is it better to use "volatile" instead of "lock" ?
                              >>>>>>
                              >>>>>Thanks,
                              >>>>>>
                              >>>>>Sam
                              >>>>>>
                              >>>>>------------------------------------------------------------
                              >>>>>We're hiring! B-Line Medical is seeking .NET
                              >>>>>Develope rs for exciting positions in medical product
                              >>>>>developmen t in MD/DC. Work with a variety of technologies
                              >>>>>in a relaxed team environment. See ads on Dice.com.
                              >>>>>
                              >>>>You can also the System.Threadin g.Interlocked class which maintains
                              >>>>volatile semantics.
                              >>>>
                              >>>You should use volatile and Interlocked together, neither fully
                              >>>replaces the other.
                              >>>>
                              >>>
                              >>Not necessarily, there is no need for volatile, as long you Interlock
                              >>consistentl y across all threads in the process. This means that once you
                              >>access a shared variable using Interlock, all threads should use
                              >>Interlock.
                              >>
                              >I don't think so, actually. Without volatile semantics, the compiler is
                              >free to cache the value of any parameter, including in/out parameters.
                              >Say you are calling an Interlocked method in a loop. If the variable is
                              >not volatile, the compiler can actually call Interlocked on a local copy,
                              >and then write the value to the real variable once, at the end of the
                              >loop (and worse, it can do so in a non-atomic way). Anything that
                              >maintains correct operation from the perspective of the calling thread is
                              >permissible for non-volatile variable access. Why would a compiler do
                              >this? For optimal use of cache. By using a local copy of a variable
                              >passed byref, locality of reference is improved, and additionally, a
                              >thread's stack (almost) never incurs cache coherency costs.
                              >>
                              >Note that this is not a problem for pass-by-pointer, which must use the
                              >true address of the referenced variable in order to enable pointer
                              >arithmetic. But pointer arithmetic isn't allowed for tracking handles, a
                              >handle is an opaque value anyway.
                              >>
                              >For lockless data structures, always use volatile. And then stick that
                              >volatile variable close in memory to what it is protecting, because CPU
                              >cache has to load and flush an entire cache line at once, and volatile
                              >write semantics require flushing all pending writes.
                              >>
                              >>>
                              >>Willy.
                              >>>
                              >>
                              >>
                              >
                              >
                              >
                              No, not at all. Interlocked operations imply a full fence, that is, reads
                              have acquire and writes have release semantics. That means that the JIT
                              may not register these variables nor store them locally and cannot move
                              stuff around them.
                              Let's look at the Win32 declaration for an Interlocked function:

                              LONG InterlockedExch ange(
                              LONG volatile* Target,
                              LONG Value
                              );Clearly, Target is intended to be the address of a volatile variable.
                              Sure, you can pass a non-volatile pointer, and there is an implicit
                              conversion, but if you do *the variable will be treated as volatile only
                              inside InterlockedExch ange*. The compiler can still do anything outside
                              InterlockedExch ange, because it is dealing with a non-volatile variable.
                              And, it can't possibly change behavior when InterlockedExch ange is called,
                              because the call could be made from a different library, potentially not yet
                              loaded.

                              Consider this:

                              /* compilation unit one */
                              void DoIt(LONG *target)
                              {
                              LONG value = /* some long calculation here */;
                              if (value != InterlockedExch ange(target, value))
                              {
                              /* some complex operation here */
                              }
                              }

                              /* compilation unit two */

                              extern void DoIt(LONG * target);
                              extern LONG shared;

                              void outer(void)
                              {
                              for( int i = 0; i < 1000; i++ )
                              {
                              DoIt(&shared);
                              }
                              }

                              Now, clearly, the compiler has no way of telling that DoIt uses Interlocked
                              access, since DoIt didn't declare volatile semantics on the pointer passed
                              in. So the compiler can, if desired, transform outer thusly:

                              void outer(void)
                              {
                              LONG goodLocalityOfR eference = shared;
                              for( int i = 0; i < 1000; i++ )
                              {
                              DoIt(&goodLocal ityOfReference) ;
                              }
                              shared = goodLocalityOfR eference;
                              }

                              Except for one thing. In native code, pointers have values that can be
                              compared, subtracted, etc. So the compiler has to honestly pass the address
                              of shared. In managed code, with tracking handles, the compiler doesn't
                              have to preserve the address of the variable (that would, after all, defeat
                              compacting garbage collection). Oh, sure, the JIT has a lot more
                              information about what is being called than a native compiler does, it
                              almost gets rid of separate compilation units.... but not quite. With
                              dynamically loaded assemblies and reflection in the mix, it is just a
                              helpless as a "compile-time" compiler.

                              I'm fairly sure that the current .NET runtime doesn't actually do any such
                              optimization as I've described. But I wouldn't bet against such things
                              being added in the future, when NUMA architectures become so widespread that
                              the compiler has to optimize for them.

                              Be safe, use volatile on every variable you want to act volatile, which
                              includes every variable passed to Interlocked.
                              Think of this, what would be the use of Interlocked operation when used in
                              languages that don't support volatile (like VB.NET) or good old C/C++
                              (except VC7 and up).
                              VC++, all versions, and all other PC compilers that I'm aware of (as in, not
                              embedded), support volatile to the extent needed to invoke an interlocked
                              operation. That is, the real variable is always accessed at the time
                              specified by the compiler. The memory fences are provided by the
                              implementation of Interlocked*, independent of the compiler version.
                              I also don't agree with your statement that you should *always* use
                              volatile in lock free or low lock scenario's. IMO, you should almost never
                              use volatile, unless you perfectly understand the semantics of the memory
                              model of the CLR/CLI (ECMA differs from V1.X differs from V2 for instance)
                              and the memory model of the CPU (IA32 vs. IA64). The last year I was
                              involved in the resolution of a number of nasty bugs , all of them where
                              the result of people trying to out-smart the system by applying lock free
                              or low lock techniques using volatile, since then whenever I see volatile
                              I'm getting very suspicious, really.......
                              You are claiming that you should almost never use lock free techniques, and
                              thus volatile should be rare. This hardly contradicts my statement that
                              volatile should always be used in lock free programming.


                              Comment

                              Working...