2

From C# - The C# Memory Model in Theory and Practice, Part 1 & 2 https://msdn.microsoft.com/en-us/magazine/jj863136.aspx
https://msdn.microsoft.com/en-us/magazine/jj883956.aspx

... the compiler and the hardware can subtly transform a program’s memory operations in ways that don’t affect the single-threaded behavior, but might affect the multithreaded behavior.

It means C# compilers can set an object reference before its constructor finish. Is readonly sufficient to write immutable objects for multi-thread?

In Java, when a field is declared as final, it is ready before the parent object reference is observable, stated in Java Language Specification 17.5
https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.5

when the object is seen by another thread, that thread will always see the correctly constructed version of that object's final fields. It will also see versions of any object or array referenced by those final fields that are at least as up-to-date as the final fields are.

Do readonly fields work the same as final in Java? Are the two pieces of code below thread-safe?
1st piece

public class A
{
    private readonly string s1;

    public A()
    {
        s1 = "abc";

    }

    public string S1 => s1;
    // or public string S1 { get; }
}

public class B
{
    private volatile A a = null; // a will not be set to null anymore

    public void SomeFunction()
    {
        Task.Run(() =>
        {
            while (a == null) ;
            Console.WriteLine(a.S1);
        });
        a = new A();
    }   
}

2nd piece

public class A
{
    private readonly string s1;

    public A()
    {
        s1 = "abc";
        Thread.MemoryBarrier();
    }

    public string S1 => s1;
}

public class B
{
    private A a = null;
    public void SomeFunction()
    {
        Task.Run(() =>
        {
            while (a == null) ;
            Console.WriteLine(a.S1);
        });
        a = new A();
    }   
}

Alternatively, A can be in this form

public class A
{
    public A()
    {
        S1 = "abc";
    }

    public string S1 { get; }
}

Can C# compilers inline the object construction like this?

public class B
{
    private viotile A a = null;
    public void SomeFunction()
    {
        Task.Run(() =>
        {
            while (a == null) ;
            Console.WriteLine(a.S1);
        });
        a = new memory for A
        a.s1 = "abc";
    }   
}

C# here means .Net Framework, .Net Core, ECMA and/or other variances


Reference Is it possible to observe a partially-constructed object from another thread?

keithyip
  • 985
  • 7
  • 21
  • We had a discussion about this a while ago when taking about the implementation of Lazy in the full framework which to my understanding would not be valid if partially constructed objects could be observed. Good question - it seems to be simply an assumption by Microsoft based on their underlying JIT but not guaranteed by the specification. It's also interesting to see that net core's implementing of Lazy was changed to not rely on any implicit guarantees here. – Voo Dec 12 '18 at 14:20
  • One of the many reasons why you should avoid lock-free programming at all costs. Even knowing if the code you have will work or not is not a trivial task. Just use a proper synchronization mechanism which will actually guarantee that the shared resource isn't accessed improperly from multiple threads. – Servy Dec 12 '18 at 14:26
  • "volatile" has an `a` in it, FYI. – Eric Lippert Dec 12 '18 at 16:48
  • By "thread safe" do you mean that these programs are guaranteed to not dereference a null `A`? – Eric Lippert Dec 12 '18 at 17:02
  • See also https://stackoverflow.com/questions/38881722/should-thread-safe-class-have-a-memory-barrier-at-the-end-of-its-constructor – Eric Lippert Dec 12 '18 at 17:04
  • Yes, thread-safe means no NullReferenceException in my example. There were locks in the example in the link. They provided implicit memory barriers. The example was thread-safe and a standard way to write thread-safe code. – keithyip Dec 13 '18 at 02:31
  • @keithyip in Java as far as I can see it would only be guaranteed thread safe if the field was final, otherwise it would depend how the instance itself is published (the original writing thread never acquires any lock). At least my understanding but I might be wrong. – Voo Dec 13 '18 at 18:40

0 Answers0