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

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Jon Skeet [C# MVP]

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

    Peter Ritchie <google.ca@pete rritchie.comwro te:
    Jon, it took me a while; but here's an example where lock doesn't work
    and you *must* use volatile to get the correct behaviour:
    Nah - I'll fix it just using an extra lock.

    <snip>
    public class Program {
    static void Main() {
    Tester tester = new Tester();
    Thread thread = new Thread(new ThreadStart(tes ter.ThreadEntry ));
    thread.Name = "Job";
    thread.Start();
    >
    Thread.Sleep(20 00);
    >
    tester.continue Running = false;
    }
    }
    >
    ... uncomment the volatile on continueRunning and it runs as
    expected, terminating after 2 seconds.
    But you've violated my conditions for correctness:

    <quote>
    The situation I've been talking about is where a particular variable is
    only referenced *inside* lock blocks, and where all the lock blocks
    which refer to that variable are all locking against the same
    reference.
    </quote>

    In particular I said:

    <quote>
    Now I totally agree that *if* you start accessing the variable from
    outside a lock block, all bets are off - but so long as you keep
    everything within locked sections of code, all locked with the same
    lock, you're fine.
    </quote>

    but by setting tester.continue Running outside the lock, you've gone
    into the "all bets are off" territory.

    Now, we don't want to start trying to acquire the lock that you've
    already got: for one thing, the object reference is never available
    outside ThreadEntry(), and for a second thing we appear to want to hold
    that lock for a long time - we'd end up in a deadlock if the looping
    thread held the lock and the thread which was trying to stop the loop
    had to wait for the loop to finish before it could acquire the lock, if
    you see what I mean.

    So, we introduce a new lock to go round every access to
    continueRunning . For ease of coding, we'll encapsulate continueRunning
    in a property access, so the complete code becomes:

    using System;
    using System.Threadin g;

    internal class Tester {
    bool continueRunning = true;

    object continueRunning Lock = new object();

    public bool ContinueRunning {
    get {
    lock (continueRunnin gLock) {
    return continueRunning ;
    }
    }
    set {
    lock (continueRunnin gLock) {
    continueRunning = value;
    }
    }
    }

    public void ThreadEntry() {
    int count=0;
    Object locker = new Object();
    lock (locker) {
    while (ContinueRunnin g) {
    count++;
    }
    }
    }
    }

    public class Program {
    static void Main() {
    Tester tester = new Tester();
    Thread thread = new Thread(new ThreadStart
    (tester.ThreadE ntry));
    thread.Name = "Job";
    thread.Start();

    Thread.Sleep(20 00);

    tester.Continue Running = false;
    }
    }

    It now works without any volatile variables (but plenty of volatile
    reads and writes!).

    --
    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

    • Jon Skeet [C# MVP]

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

      On Jul 10, 7:52 am, Jon Skeet [C# MVP] <s...@pobox.com wrote:

      <snip>
      Did you read the section of Grant's page about the locking protocol, by
      the way?
      Oops - Vance's page, that is.

      Jon

      Comment

      • Jon Skeet [C# MVP]

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

        Peter Ritchie [C#MVP] <prsoco@newsgro ups.nospamwrote :

        <snip>
        Besides, I think we've sufficiently broken
        Microsoft's online newsgroup reader with regard to this thread.
        Agreed. I can address any of the points in your most recent post if you
        really wish me to, but I suspect we're not going to convince each
        other. However, we might at least be able to agree what we
        agree/disagree on, which could serve as a useful summary of the thread
        for anyone looking at it in the future. Here's what I believe - please
        correct as appropriate :) (It's at a pretty high level to try to steer
        clear of controversy.)


        Things we agree on:

        1) ECMA 335 is a weaker memory model than the .NET 2.0 model
        2) ECMA 335 should be clearer
        3) Variables declared as volatile have useful semantics, i.e. a change
        made in one thread will be immediately visible in all other threads
        4) If you use the locking protocol (as described by Vance) you don't
        need to make variables volatile when running the .NET 2.0 CLR


        Beliefs I hold:
        1) Point 4 is also valid for the ECMA spec, i.e. ECMA 335 guarantees
        that the locking protocol "works"
        2) The ECMA spec should be deemed to govern overall visible system
        behaviour, rather than only specifying what the JIT can do vs what the
        CPU can do, unless it explicitly states that


        Beliefs I believe you hold:
        1) The locking protocol isn't guaranteed to work for all ECMA 335
        compliant CLRs
        2) There are places in the ECMA spec are implicitly only specifying
        behaviour of the CPU or behaviour of the JIT compiler, rather than
        overall visible system behaviour

        --
        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

        • Barry Kelly

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

          Peter Ritchie [C#MVP] wrote:
          Here are my positions (which overlap with your post):
          1. "Acquire semantics" and "release semantics" have to do with processor
          cachings, not compiler optimizations,
          I don't think this is entirely true, for at least one important reason:
          the CPU is an implementation detail, and what's important is that the
          programmer's intent when the code is written is respected no matter how
          many layers of software or hardware through which the code gets
          transmitted and transmuted, where the programmer from the CLI's
          perspective is the compiler writer. If this wasn't the case, acquire and
          release guarantees wouldn't have any weight, since they could be
          discarded by the optimizer through its manipulations.

          -- Barry

          --

          Comment

          • Peter Ritchie [C#MVP]

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

            "Barry Kelly" <barry.j.kelly@ gmail.comwrote in message
            news:2vne935e9r abse58ek64g6uub tajuj8chk@4ax.c om...
            Peter Ritchie [C#MVP] wrote:
            >
            >Here are my positions (which overlap with your post):
            >1. "Acquire semantics" and "release semantics" have to do with processor
            >cachings, not compiler optimizations,
            >
            I don't think this is entirely true, for at least one important reason:
            the CPU is an implementation detail, and what's important is that the
            programmer's intent when the code is written is respected no matter how
            many layers of software or hardware through which the code gets
            transmitted and transmuted, where the programmer from the CLI's
            perspective is the compiler writer. If this wasn't the case, acquire and
            release guarantees wouldn't have any weight, since they could be
            discarded by the optimizer through its manipulations.
            I agree that there needs to be a specification for what can and cannot be
            optimized. But, I don't think "acquire semantics" and "release semantics"
            are sufficient. They're not defined within 335. Outside of 335, all
            references that I've read, deal strictly with flushing of the processor's
            write cache and are not in a context relative to any compiler. If a
            processor were truly an implementation detail there would be no need for
            MemoryBarrier, VolatileRead, etc. There are details to some processors
            whose consequences leak out into our programming models and must be
            compensated for, good or bad. 335 compensates for this by reusing the
            acquire/release semantics terms and mandates they be dealt with with all
            volatile operations. The new C++ spec. finally tries to compensate for
            these issues as well. I believe the new Java memory model is also
            compensating for them as well. Historically these languages did leave the
            processor as an implementation detail: a black box; but that has meant it's
            very complicated to write thread-safe code. Look at
            http://www.devarticles.com/c/a/Cplus...00-ThreadSafe/,
            or http://www.javaworld.com/jw-02-2001/...le.html?page=1. It's
            impossible to currently write a thread-safe double-check lock pattern with
            strictly ISO C++ code, you have to inject some sort of platform-specific
            code to do it.

            As far as I know, 335 is the only ratified standard that does attempt to
            deal with processor write caching, and that's great. That's a huge step
            towards being able to write truly thread-safe code; but programmers still
            needs to use the language syntax given to them to explicitly say what is and
            isn't a thread-shared variable, with C++/CLI, ISO C++, Java (prior to 5.0)
            this was done with the "volatile" keyword to tell the compiler to emit a
            processor instruction to access RAM in the sequence detailed in the source
            code, relative to all other volatile operators, the current blocks interface
            requirements, and a single thread of execution.


            Comment

            • Peter Ritchie [C#MVP]

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

              Okay, so we know .NET 2.0 is violating 335, i.e. it's not CLI-compliant,
              with respect to the memory model. Where else is it violating the 335 memory
              model? We don't know.

              Not big news that .NET 2.0 isn't CLI-compliant, many have argued the 335
              memory model (although stricter than most language-specification and
              framework memory models) is broken and Vance details how they've tried to
              fix it in .NET 2.0. In the general case, maybe it's true that the ECMA
              model is broken; from many programmer's points of view: certainly not; they
              can still write thread-safe code.

              So, where does that leave designers and programmers with respect to
              developing something for a .NET platform that we can be certain is
              thread-safe? Kinda up that creek without a compliant paddle. We could fall
              back to our language specifications and reference material on MSDN and
              assume they're all wrong when contradicted by Vance's .NET 2.0 memory model
              article. But, the problem is even Vance's article is contradictory to what
              the .NET 2.0 JIT is doing. Even then, I'd argue that Vance's article is
              anecdotal and has been contradicted by other's of equal stature. Look at
              Vance's assertion: "...so all practical memory models have the following
              three fundamental rules: 1. The behaviour of the thread when run in
              isolation is not changed. Typically, this means that a read or a write from
              a given thread to a given location cannot pass a write from the same thread
              to the same location. 2. Reads cannot move before entering a lock. 3. Writes
              cannot move after exiting a lock." The only time 2 & 3 hold true, even in
              ..NET 2.0, is in the context of processor write-cache flushing (e.g. the x86
              and IA64 memory models; they can't deal with re-sequencing of instructions
              because it's outside their control).

              Sure, we can say he "meant" something more detailed (like heap memory, not
              stack memory); but how do we get that detail out to the development
              community? It's impossible.

              But, the JIT isn't following the rules that he's detailed unless they only
              have to do with processor write-caching.

              Also, why should it distinguish between stack and heap memory? Why should
              stack memory be disregarded with respect to these rules? What if I were
              writing an synchronous method that called an asynchronous method that
              accepted a memory reference? If I pass it a reference to stack memory,
              there's nothing I can do to tell the compiler that variable should be
              treated as volatile by the JIT. For example:
              public int Method( )
              {
              double value1 = 3.1415;
              int value2 = 42;
              IAsyncResult result = BeginBackground Operation(ref value1, ref value2);

              // Sit in a loop waiting for up to 250ms at a time
              // doing something with the double value...
              do
              {
              value2 = 5;
              // doubles aren't atomic, we need to use
              // VolatileRead to read the "latest written" value and
              // because BeginBackground Operation uses
              // Thread.Volatile Write(ref double).
              double temp = Thread.Volatile Read(ref value1);
              Thread.Sleep(va lue2);
              // ...
              } while (!result.AsyncW aitHandle.WaitO ne(250, false));
              return 1;
              }

              If the rules only applied to heap memory then that *could* be optimized to
              public int Method( )
              {
              double value1 = 3.1415;
              int value2 = 42;
              IAsyncResult result = BeginBackground Operation(ref value1, ref value2);

              do
              {
              double temp = Thread.Volatile Read(ref value1);
              Thread.Sleep(5) ;
              } while (!result.AsyncW aitHandle.WaitO ne(250, false));
              return 1;
              }

              I use Thread.Sleep not because it makes sense in this example, only that it
              makes the disassembly easier to read for passing a value to a method.
              Something like Console.WriteLi ne would make more sense but that means the
              possibility of injecting a some standard output initialization code that
              complicates the disassembly.

              Good design? Probably not; if I had to review that code I'd likely send it
              back for re-write. But if those rules apply to JIT optimization as well as
              processor write-caching then the only description of the .NET 2.0 memory
              model and the ECMA memory model say it's thread-safe with regard to value1.

              "Jon Skeet [C# MVP]" <skeet@pobox.co mwrote in message
              news:MPG.21012e c6eb9cfbc52d9@m snews.microsoft .com...
              Peter Ritchie [C#MVP] <prsoco@newsgro ups.nospamwrote :
              <snip>
              The violations that you're seeing (well, they're violations of the way
              I read the spec, anyway) - do they occur when reading and writing heap
              memory "around" a volatile member, or only when reading and writing
              stack value?
              <snip>


              Comment

              • Jon Skeet [C# MVP]

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

                Peter Ritchie [C#MVP] <prsoco@newsgro ups.nospamwrote :

                <snip>
                Also, why should it distinguish between stack and heap memory? Why should
                stack memory be disregarded with respect to these rules? What if I were
                writing an synchronous method that called an asynchronous method that
                accepted a memory reference? If I pass it a reference to stack memory,
                there's nothing I can do to tell the compiler that variable should be
                treated as volatile by the JIT. For example:
                public int Method( )
                {
                double value1 = 3.1415;
                int value2 = 42;
                IAsyncResult result = BeginBackground Operation(ref value1, ref value2);
                Do you have an example of this sort of asynchronous behaviour which
                actually works? Delegate.BeginI nvoke has different behaviour for
                ref/out parameters than for value parameters - you fetch them
                separately when you call EndInvoke. In other words it doesn't update
                the values you provide in the call to BeginInvoke. That's not to say
                that other framework calls *don't* work in the way you describe - but
                I've never seen one. Do you have an example?

                The problem is - what would you expect to happen if Method() just
                returned at this point, thus popping the stack frame? It would be
                *hugely* unsafe to let another thread start arbitrarily writing to
                stack data for a different thread. I don't *believe* it's possible to
                do in safe C# code, although it could be possible with unsafe code.

                I think it's fundamentally a bad idea for one thread to access memory
                in another thread's stack (except in very controlled environment such
                as a debugger) - I think it's reasonable to put that (explicitly, mind)
                outside the restrictions of the locking protocol.
                // Sit in a loop waiting for up to 250ms at a time
                // doing something with the double value...
                do
                {
                value2 = 5;
                // doubles aren't atomic, we need to use
                // VolatileRead to read the "latest written" value and
                // because BeginBackground Operation uses
                // Thread.Volatile Write(ref double).
                Even if doubles were treated atomically, that wouldn't mean you'd still
                get the "latest written" value. It just means you'd either get the new
                value or the old one, not a "half way house".

                --
                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]

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

                  "Peter Ritchie [C#MVP]" <prsoco@newsgro ups.nospamwrote in message
                  news:eKNnI1nxHH A.3588@TK2MSFTN GP06.phx.gbl...
                  >I was thinking more in the context of a PInvoke call; but I did mix in some
                  >asynchronous call patterns in there... But, with PInvoke it's going to
                  >marshal those pointers and the background thread wouldn't be directly
                  >updating the stack variable's value either. Although not relevant, it
                  >doesn't cause an access violation if the loop doesn't end while the
                  >background thread is running (didn't try breaking the loop and exiting the
                  >method before the thread completed; so, I don't know if it causes a
                  >violation, my guess it wouldn't until the next GC...).
                  >
                  I haven't tried it; but my guess is you'd have to use an unsafe method in
                  C# to get the address of a stack variable to a background thread. Not
                  really worth doing because of the obvious problems; but the JIT doesn't
                  know that.
                  >
                  Oddly, the JIT doesn't do any optimizations on the integer as long as I
                  pass them by ref to another method. It's almost as if the JIT thinks the
                  address could have been passed to another thread (I can't think of any
                  other reason why it should't before that optimization). But, far from
                  proof of anything...
                  >
                  You're more comfortable with saying that .NET 2.0 is violating both the
                  spec and Vance's .NET 2.0 memory model article (as written) than to say
                  they deal with processor write-cache flushing? 335 does have that over
                  other language specs., which goes a long way towards being able to
                  reliably write platform-independent thread-safe code. Something you can't
                  say for some other languages yet.
                  >
                  I've gone through Vance's article [1] again and it does say the
                  double-check lock pattern works without making the instance member
                  volatile; while Joe Duffy says on IA64 no instructions are generated with
                  the acq or rel completer without declaring a member "volatile" [2]...
                  What Joe says is this:
                  "The 2.0 memory model does not use ld.acq’s unless you are accessing
                  volatile data (marked w/ the volatile modifier keyword or accessed via the
                  Thread.Volatile Read API)."
                  which means that reads have acquire semantics when interlocked (reads of
                  "volatile" fields or volatile read operations), all writes have release
                  semantics since v 2.0, that means that all stores have release semantics
                  (st.rel instruction on IA64), irrespective the current HW platform.

                  To save you scouring
                  Vance's article, it's the last sentence paragraph 3 of the section
                  Technique 4: Lazy Initialization. "In the .NET Framework 2.0 model, the
                  code works without the volatile declarations.", in reference to Figure 7
                  which is:
                  public class LazyInitClass {
                  private static LazyInitClass myValue = null;
                  private static Object locker = new Object();
                  >
                  public static LazyInitClass GetValue() {
                  if (myValue == null) {
                  lock(locker) {
                  if (myValue == null) {
                  myValue = new LazyInitClass() ;
                  }
                  }
                  }
                  return myValue;
                  }
                  };
                  >
                  Above sample works on IA64 as is , what doesn't work and what Joe is talking
                  about is a" slight variant " of the above, marking the fields volatile in
                  Joe's sample doesn't work either, you must use explicit barriers.



                  Willy.

                  Comment

                  • Peter Ritchie [C#MVP]

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


                    "Willy Denoyette [MVP]" <willy.denoyett e@telenet.bewro te in message
                    news:%233k01ftx HHA.3400@TK2MSF TNGP03.phx.gbl. ..
                    "Peter Ritchie [C#MVP]" <prsoco@newsgro ups.nospamwrote in message
                    news:eKNnI1nxHH A.3588@TK2MSFTN GP06.phx.gbl...
                    <snipWhat Joe says is this:
                    "The 2.0 memory model does not use ld.acq’s unless you are accessing
                    volatile data (marked w/ the volatile modifier keyword or accessed via the
                    Thread.Volatile Read API)."
                    which means that reads have acquire semantics when interlocked (reads of
                    "volatile" fields or volatile read operations), all writes have release
                    semantics since v 2.0, that means that all stores have release semantics
                    (st.rel instruction on IA64), irrespective the current HW platform.
                    Right, changing the double-checked lock pattern to use an additional boolean
                    won't work (and is no longer the double-check lock pattern) because it's not
                    guarding the complex (non-atomic) invariant (the bool AND the instance) so
                    it must change to the single-check lock pattern and take the performance
                    hit. I wasn't saying the non-double-check lock pattern worked, only that
                    Joe has detailed that ld.acq is not emitted unless the field is declared
                    volatile.

                    In the "working" double-check lock the first read of "myValue" (comparing to
                    null) is not volatile if "myValue" is not volatile. There's no acquire
                    semantics until the lock statement. The write to "myValue" within the lock
                    block is also not volatile, but it's guarded. So, immediately after the
                    write to "myValue" any non-volatile access to "myValue" by another processor
                    may not see that write as it may have been cached. The end of the lock
                    block flushes the write-cache; and if that write was cached it is now
                    flushed. And if there's any code after that write and before the end of the
                    lock block (that isn't a volatile operation), you increase the liklihood of
                    executing code after the write in the processors' instruction sequence
                    without "seeing" it. Declaring "myValue" volatile causes the comparision of
                    null to see any cached writes as well as the write to "myValue" in the lock
                    block to be visible to all other processors.
                    To save you scouring
                    >Vance's article, it's the last sentence paragraph 3 of the section
                    >Technique 4: Lazy Initialization. "In the .NET Framework 2.0 model, the
                    >code works without the volatile declarations.", in reference to Figure 7
                    >which is:
                    >public class LazyInitClass {
                    > private static LazyInitClass myValue = null;
                    > private static Object locker = new Object();
                    >>
                    > public static LazyInitClass GetValue() {
                    > if (myValue == null) {
                    > lock(locker) {
                    > if (myValue == null) {
                    > myValue = new LazyInitClass() ;
                    > }
                    > }
                    > }
                    > return myValue;
                    > }
                    >};
                    >>
                    >
                    Above sample works on IA64 as is
                    Do you have IA64 disassembly of Vance's sample code to show that
                    "if(myValue==nu ll)" emits an instruction with the "acq" completer contrary
                    to Joe's "The 2.0 memory model does not use ld.acq’s unless you are
                    accessing volatile data..." statement?


                    Comment

                    • Barry Kelly

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

                      Peter Ritchie [C#MVP] wrote:
                      Also, why should it distinguish between stack and heap memory? Why should
                      stack memory be disregarded with respect to these rules?
                      Because the stack is associated with a single thread of execution, and
                      references to stack locations cannot be communicated between threads
                      using verifiable code.
                      What if I were
                      writing an synchronous method that called an asynchronous method that
                      accepted a memory reference?
                      For standard .NET asynchronous method pattern methods, these variables
                      are copied in and out. A reference isn't kept.

                      -- Barry

                      --

                      Comment

                      • Peter Ritchie [C#MVP]

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

                        Yes, from a design standpoint it's really bad idea. But the JIT has to
                        support unverifiable code and cannot make the decision what is and isn't bad
                        code and has to assume whatever the language-to-IL compiler gave it is valid
                        code. So, it stands to reason that it still has to consider stack
                        variables. Regardless, the .NET 2.0 memory model description and the CLI
                        spec both don't distinguish and just detail "any memory" or just "memory".

                        C# and .NET move the gun much farther away from your foot; but if you aim
                        really carefully you can still shoot it.


                        "Barry Kelly" <barry.j.kelly@ gmail.comwrote in message
                        news:764n93dn2b 8be55b8rma8f7nt 11ngdj97i@4ax.c om...
                        Peter Ritchie [C#MVP] wrote:
                        >
                        >Also, why should it distinguish between stack and heap memory? Why
                        >should
                        >stack memory be disregarded with respect to these rules?
                        >
                        Because the stack is associated with a single thread of execution, and
                        references to stack locations cannot be communicated between threads
                        using verifiable code.
                        >
                        >What if I were
                        >writing an synchronous method that called an asynchronous method that
                        >accepted a memory reference?
                        >
                        For standard .NET asynchronous method pattern methods, these variables
                        are copied in and out. A reference isn't kept.

                        Comment

                        • Jon Skeet [C# MVP]

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

                          Peter Ritchie [C#MVP] <prsoco@newsgro ups.nospamwrote :
                          Yes, from a design standpoint it's really bad idea. But the JIT has to
                          support unverifiable code and cannot make the decision what is and isn't bad
                          code and has to assume whatever the language-to-IL compiler gave it is valid
                          code.
                          I think it's entirely reasonable for the memory model to allow some
                          optimisations which will only break code which is doing fundamentally
                          dangerous things in the first place.

                          In particular, if you're using unsafe code you're *likely* to be
                          calling into native code - at which point you've got a whole other
                          memory model to worry about to start with. You've got to worry about
                          when the native code will publish writes, as well as when the managed
                          code will read them.
                          So, it stands to reason that it still has to consider stack
                          variables. Regardless, the .NET 2.0 memory model description and the CLI
                          spec both don't distinguish and just detail "any memory" or just "memory".
                          Indeed - and I believe they should do so.
                          C# and .NET move the gun much farther away from your foot; but if you aim
                          really carefully you can still shoot it.
                          True - but I see no reason why they should help to keep you thread-safe
                          while you shoot yourself.

                          --
                          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

                          • Jon Skeet [C# MVP]

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

                            Peter Ritchie [C#MVP] <prsoco@newsgro ups.nospamwrote :

                            <snip>

                            Is anyone still interested in me replying to this post? I've left it
                            for a while because it'll take a fair amount of replying, but I won't
                            bother if no-one's interested any more :)

                            --
                            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

                            • =?ISO-8859-1?Q?Arne_Vajh=F8j?=

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

                              Jon Skeet [C# MVP] wrote:
                              Is anyone still interested in me replying to this post? I've left it
                              for a while because it'll take a fair amount of replying, but I won't
                              bother if no-one's interested any more :)
                              I consider it very likely that someone will find it useful
                              within the next 5-10 years.

                              Besides the original poster and participants, then there
                              are always those that find the thread via Google later.

                              Arne

                              Comment

                              • Jon Skeet [C# MVP]

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

                                Arne Vajhøj <arne@vajhoej.d kwrote:
                                Jon Skeet [C# MVP] wrote:
                                Is anyone still interested in me replying to this post? I've left it
                                for a while because it'll take a fair amount of replying, but I won't
                                bother if no-one's interested any more :)
                                I consider it very likely that someone will find it useful
                                within the next 5-10 years.

                                Besides the original poster and participants, then there
                                are always those that find the thread via Google later.
                                Okay - I'll try to reply on Sunday/Monday then. I'm away until then.

                                --
                                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

                                Working...