C#线程安全和具有只读字段或属性的部分构造的对象

时间:2018-12-12 14:01:40

标签: c# multithreading constructor synchronization thread-safety

来自C#-理论和实践中的C#内存模型,第1部分和第2部分 https://msdn.microsoft.com/en-us/magazine/jj863136.aspx
https://msdn.microsoft.com/en-us/magazine/jj883956.aspx

  

...编译器和硬件可以巧妙地转换程序的内存   操作不会影响单线程行为,但是   可能会影响多线程行为。

这意味着C#编译器可以在构造函数完成之前设置对象引用。 readonly是否足以为多线程编写不可变的对象?

在Java中,当字段声明为final时,在Java语言规范17.5中所述,该字段在父对象引用可观察之前就已准备就绪。 https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.5

  

当另一个线程看到该对象时,该线程将始终可见   该对象最终字段的正确构造版本。它   还将看到那些引用的任何对象或数组的版本   最终字段至少与最终字段一样最新。

在Java中,只读字段的作用与final相同吗?下面的两段代码是线程安全的吗?
第一件

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();
    }   
}

第二张

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();
    }   
}

或者,A可以采用这种形式

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

    public string S1 { get; }
}

C#编译器可以像这样内联对象构造吗?

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#在这里是指.Net Framework,.Net Core,ECMA和/或其他版本


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

0 个答案:

没有答案