Coder Social home page Coder Social logo

Comments (5)

bcuff avatar bcuff commented on June 10, 2024
  1. The volatile is still necessary because otherwise there would be no fence between the initialization of the object and the assignment to the field otherwise. A new thread could then come along and get the newly published object from the field without a fence and read stale memory all before the initializing thread exited the lock.
  2. Ah! Thanks for letting me know. I'll fix that in the docs. The actual implementation does the right thing.
  3. You're right, if the is a reference type it would be a good idea to do the standard if (x == null) throw new ArgumentNullException(...). As is, it would likely lead to a different ArgumentNullException in the call to Dictionary.Add(...)

from autolazy.

airbreather avatar airbreather commented on June 10, 2024

The volatile is still necessary because otherwise there would be no fence between the initialization of the object and the assignment to the field otherwise. A new thread could then come along and get the newly published object from the field without a fence and read stale memory all before the initializing thread exited the lock.

If there are problems without volatile, then I don't think volatile can solve those problems. If I'm wrong, feel free to provide a more detailed sequence of events, ideally with an explanation of why you think it's a problem.

The only problem I can think of is if the field is of a struct type where the struct is larger than the size of a single object reference... but you actually cannot declare such a field as volatile in the first place, presumably because of the issue I'm worried about. I'm guessing you just don't allow that here, but if you do want to try to support it, I think you'd need to do most of your checks on a synthetic field of a type that isn't susceptible to struct tearing, and only read the payload once you can guarantee it's fully written.

Otherwise, from your description, it sounds like you're concerned about letting a later thread see the results before the initializing thread is finished publishing it to its own consumer (perhaps because the initializing thread has its own state to clean up; in your example, this would be disposing the FileStream and calling Monitor.Exit). I personally don't see a problem with that. Regardless of my opinion, though, if it is a problem, then again it doesn't look like volatile solves it: this happens whether you have volatile or not. I think if you want to make sure that nobody gets the initialized object before the initializing thread gets its own, without "punishing" everyone who comes around long after the initialization is done, then you might need an additional synchronization mechanism like a ManualResetEvent... not sure, didn't think about it too much.

Worst-case without volatile is that, the later thread happened to read a null even though the initializing thread thinks it's already written the initialized value, in which case the later thread has to go into the lock to fetch the guaranteed non-null value. There's a very narrow window where this can happen, and in that narrow window I believe the behavior is correct because Monitor.Enter / Monitor.Exit are both full-fence AFAIK.

from autolazy.

bcuff avatar bcuff commented on June 10, 2024

Without the volatile this optimization is possible:

    public static List<string> Settings
    {
        get
        {
            // thread-safe double-checked locking pattern generated here
            var result = _settings;
            if (result == null)
            {
                lock(_syncRoot) // fence (re-ordering instructions around this comment is not allowed)
                {
                    // however, re-ordering instructions within the lock IS allowed
                    var result = _settings;
                    if (result == null)
                    {
                        // the compiler / jit / underlying hardware may choose to assign _settings here instead of at the bottom. This is allowed unless _settings is declared volatile.
                        var settings = new List<string>();
                        settings.Add("foo");
                        settings.Add("bar");
                        _settings = settings; // this must be volatile else it may be moved to the above comment.
                    }
                } // fence (re-ordering instructions around this comment is not allowed)
            }
            return result;
        }
    }

from autolazy.

bcuff avatar bcuff commented on June 10, 2024

Also see http://stackoverflow.com/questions/3578604/how-to-solve-the-double-checked-locking-is-broken-declaration-in-java#answer-3580658

This is Java, however, it is also applicable to c#. I believe the standard windows runtime does not allow write reordering so you can get away with not declaring it volatile, however this guarantee may not hold true in the future or for other runtimes.

from autolazy.

airbreather avatar airbreather commented on June 10, 2024

I see... I was thinking just x86/x64, but I guess CPUs in other families might have a memory model that doesn't guarantee that this would be correct without volatile.

from autolazy.

Related Issues (7)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.