views:

964

answers:

7

I would like to know if C# automatically implemented properties like "public static T Prop{get;set;}", are thread safe or not. Thanks!

+2  A: 

No, they not threadsafe. Static properties just as vulnerable as static fields are to concurrency issues.

gWiz
+3  A: 

I don't believe so. I believe they are just syntatic sugar for:

private static T _prop;
public static T Prop
{
    get { return _prop; }
    set { _prop = value; }
}
Nick
+2  A: 

No. You must wrap them in thread-locking mechanisms.

object _lock = new object();
public static Main(string[] args)
{
    lock(_lock)
    {
         Prop = new T();
    }


    T val = null;
    lock(_lock)
    {
         val = Prop;
    }
}
yodaj007
What is Prop? What is T?
gWiz
Prop and T are from the question.
yodaj007
+10  A: 

It appears not. This is the decompilation with Reflector:

private static string Test
{
    [CompilerGenerated]
    get
    {
        return <Test>k__BackingField;
    }
    [CompilerGenerated]
    set
    {
        <Test>k__BackingField = value;
    }
}
qstarin
That's kind of wrong. .NET's memory model guarantees that writes to them will be atomic and seen by all threads, at least for the regular .NET Framework, and if they are not virtual they will always be inlined. Both are implementation details of the .NET desktop framework and are not guaranteed by the spec, though.
Robert Fraser
er I mean the decompilation is correct, but the way they are implemented guarantees atomicity, at least for integers and reference types (with the obvious caveat that atomicity != thread safety). For longs/doubles/structs/etc., you're on you're on your own, though.
Robert Fraser
The spec guarantees that things like `Int32`, `float` and references are **atomic**. It doesn't make many guarantees about thread visibility / register caching etc.
Marc Gravell
is that k__BackingField that you decompiled volatile?
Miguel Angelo
Err... isn't that kind of the definition of atomic?: http://en.wikipedia.org/wiki/Atomicity_%28programming%29 ... At least on x86/x64, a fence after write should be sufficient to guarantee that "if one thread sees it, all threads see it".
Robert Fraser
As I understand it in this context, "atomic" means that it can't be seen mid-update. For example, `double` is not guaranteed atomic; if you change a double field from {x} to {y}, another thread could see it after only the first half has been updated - it could get a **different** number ({z}) that has **never** existed as a "real" value of the field (huge corruption issue).
Marc Gravell
I think atomic is defined as "in one, unsplitable step"... such that nothing happens concurrently with that instruction... but it does not mean that, it will sync processor caches... if that was automatic, multiprocessing would have no meaning at all
Miguel Angelo
I'm wrong, it is not that it does not have concurrency, but that it can not be broken, once it has started.
Miguel Angelo
@Miguel: No, it is not volatile. I apologize for not responding sooner, busy day and all ...
qstarin
volatile = the compiler will not reorder it.
Robert Fraser
+2  A: 

There is no synchronization provided with automatic properties, including static properties.

If you need full thread safety, you'll want to use your own properties with a backing field, and handle the synchronization yourself.

Reed Copsey
+3  A: 

For completeness, field-like events do have thread-safety built in, but they are alone in this. Automatically implemented properties do not have any such features. You can, however, do something like:

public static double SomeProp
{   // ### NOT RECOMMENDED ###
    [MethodImpl(MethodImplOptions.Synchronized)] get;
    [MethodImpl(MethodImplOptions.Synchronized)] set;
}

The problem with this is that it will lock the Type, which is a bad thing. I would implement my own synchronization for this, personally.

Marc Gravell
"bad" for reasons of "marshal-by-bleed" where the Type lock bleeds into other isolated appdomains in the same process...
x0n
It is bad enough just with one app-domain truth be told.
Marc Gravell
+15  A: 

Section 10.7.4 of the C# specification states:

When a property is specified as an automatically implemented property, a hidden backing field is automatically available for the property, and the accessors are implemented to read from and write to that backing field. The following example:

public class Point {
  public int X { get; set; } // automatically implemented
  public int Y { get; set; } // automatically implemented
}

is equivalent to the following declaration:

public class Point {
  private int x;
  private int y;
  public int X { get { return x; } set { x = value; } }
  public int Y { get { return y; } set { y = value; } }
}

That's what we promise, and that's what you get. The point of auto properties is to do the most basic, simple, cheap thing; if you want to do something fancier then you should write a "real" property.

Eric Lippert
Upvoted you for referencing the actual C# specification.
qstarin