And*_*tos 3 c# atomic value-type thread-safety tearing
值类型的分配是否在 .Net 中被认为是原子的?
例如,考虑以下程序:
struct Vector3
{
public float X { get; private set; }
public float Y { get; private set; }
public float Z { get; private set; }
public Vector3(float x, float y, float z)
{
this.X = x;
this.Y = y;
this.Z = z;
}
public Vector3 Clone()
{
return new Vector3(X, Y, Z);
}
public override String ToString()
{
return "(" + X + "," + Y + "," + Z + ")";
}
}
class Program
{
private static Vector3 pos = new Vector3(0,0,0);
private static void ReaderThread()
{
for (int i = 0; i < int.MaxValue; i++)
{
Vector3 v = pos;
Console.WriteLine(v.ToString());
Thread.Sleep(200);
}
}
private static void WriterThread()
{
for (int i = 1; i < int.MaxValue; i++)
{
pos = new Vector3(i, i, i);
Thread.Sleep(200);
}
}
static void Main(string[] args)
{
Thread w = new Thread(WriterThread);
Thread r = new Thread(ReaderThread);
w.Start();
r.Start();
}
}
Run Code Online (Sandbox Code Playgroud)
像这样的程序会受到高级数据竞争的影响吗?甚至是数据竞赛?
我想知道的是: v 是否有可能包含:
小智 8
结构是值类型。如果将结构体分配给变量/字段/方法参数,则整个结构体内容将从源存储位置复制到变量/字段/方法参数的存储位置(每种情况下的存储位置都是结构本身)。
复制结构不能保证是原子操作。正如C# 语言规范中所写:
变量引用的原子性
以下数据类型的读取和写入是原子的:bool、char、 byte、sbyte、short、ushort、uint、int、float和引用类型。此外,具有前面列表中的基础类型的枚举类型的读取和写入也是原子的。读取和写入其他类型,包括long、ulong、double和decimal以及用户定义的类型,不能保证是原子的。除了为此目的设计的库函数外,无法保证原子读-修改-写,例如在递增或递减的情况下。
所以是的,当一个线程正在从结构存储位置复制数据的过程中,另一个线程出现并开始将新数据从另一个结构复制到该存储位置时,可能会发生这种情况。因此,从存储位置复制的线程最终可能会复制旧数据和新数据的混合。
作为旁注,由于您的一个线程如何写入变量以及另一个线程如何使用该变量,您的代码还可能会遇到其他并发问题。(用户acelent对另一个问题的回答在技术细节上很好地解释了这一点,因此我将参考它:https : //stackoverflow.com/a/46695456/2819245)您可以通过封装此类的任何访问来避免此类问题块中的“线程交叉”变量lock。作为替代lock,而对于基本数据类型,你也可以使用通过所提供的方法Interlocked在一个线程安全的方式(在两者之间类来访问线程交叉变量/场交替lock和Interlocked 但是,用于相同线程交叉变量的方法不是一个好主意)。
| 归档时间: |
|
| 查看次数: |
1290 次 |
| 最近记录: |