C # потокобезопасность и частично построенные объекты с полями или свойствами только для чтения - PullRequest
0 голосов
/ 12 декабря 2018

Из 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

, когда объект виден другим потоком, этот поток всегда будет видеть правильно построенную версию конечных полей этого объекта.Он также будет видеть версии любого объекта или массива, на которые ссылаются эти последние поля, которые, по крайней мере, так же актуальны, как и последние поля.

Поля, доступные только для чтения, работают так же, как final в Java?Являются ли две части кода ниже поточно-ориентированными?
1-ая часть

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

2-ая часть

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 и / или другие варианты


Ссылка Можно ли наблюдать частично построенный объект из другого потока?

...