来自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?