10

What will happen if two threads read this property at the same time?

public static HugeType HugeType
{
    get
    {
        if (tenderCache == null)
        {
            tenderCache = Config.Get<HugeType>("HugeType", null);
        }
        return tenderCache;
    }
}

My object is read only and it's not critical if two instances are created. Should I add locks in any case?

4444
  • 3,523
  • 10
  • 27
  • 43
Ievgen Naida
  • 3,596
  • 6
  • 64
  • 117
  • 1
    Note that in memory models weaker than the .NET model, it might be possible for other threads to see a non-null `tenderCache` reference, but the object it refers to is not yet fully constructed. For example this is definitely a data race in C++. – Ben Voigt Sep 24 '14 at 15:50
  • 1
    `Config.Get("HugeType", null)` may be invoke more than once and last thread wins. If that doesn't hurts you, you don't need a lock. – Sriram Sakthivel Sep 24 '14 at 15:55
  • 3
    I'd suggest looking at [this](http://stackoverflow.com/questions/6847721/when-should-i-use-lazyt) question. Lazy is what you want here. – Daniel Kelley Sep 24 '14 at 15:55
  • 1
    How is Config.Get implemented ? Are you ok if it's called from multiple threads at the same time? – Andrey Taptunov Sep 24 '14 at 15:56

1 Answers1

9

Because you have no synchronization it's possible for the initialization method to be called many times, possibly even if other threads have completed the initialization entirely (due to a lack of a memory barrier). If you don't care about executing the initialization operation multiple times and it will always return the same correct value regardless of how many times it's called and even if multiple calls to it are made concurrently, then the code will certainly work, even if it won't perform as well.

Having said that, actually properly ensuring that the initialization is only done once is very easy, given that it's already a solved problem. You can simply store a Lazy<HugeType> in your field instead of a HugeType and Lazy will take care of the initialization synchronization for you.

Servy
  • 193,745
  • 23
  • 295
  • 406
  • 1
    +1 What happens if two threads get (tenderCache == null) as true and both try and write to tenderCache = Config.Get("HugeType", null); at the same time? Or the first (tenderCache == null) as true tries to read tenderCache while the second is writing to it. – paparazzo Sep 24 '14 at 16:04
  • 2
    @Blam If both try to write the value then one will win; assuming the initialization is always creating the same value, it means that it won't matter who wins. Writes to variables of a reference type are atomic, so if the value is being read while another thread is trying to write to it either the read happens before the write, or the write happens before the read, and those are the only options. Getting garbage, or "the world ending" aren't possibilities. – Servy Sep 24 '14 at 16:06
  • 1
    This is actually ripe for a thread issue and so be aware of the problems that exist if you had more lines in the initialization such as adding elements to a collection. The additional lines of code inside the null check could be missed due to the conditional no longer being true eg tenderCache == null – Firegarden Jul 01 '17 at 05:35