C# 在多线程程序中未读取正确的属性值
我遇到了这样一种情况:我不确定为什么在多个线程中没有从属性中读取正确的属性值。。我已经编写了一个小的控制台应用程序来说明这种情况C# 在多线程程序中未读取正确的属性值,c#,.net,C#,.net,我遇到了这样一种情况:我不确定为什么在多个线程中没有从属性中读取正确的属性值。。我已经编写了一个小的控制台应用程序来说明这种情况 class Program { private static Test MyObject; static void Main(string[] args) { MyObject = new Test(); Task.Run(() => { var obj = MyO
class Program
{
private static Test MyObject;
static void Main(string[] args)
{
MyObject = new Test();
Task.Run(() =>
{
var obj = MyObject as Test;
Console.WriteLine("1: " + obj.MyValue);
Update("Thread1");
Console.WriteLine("2: " + obj.MyValue);
});
Task.Run(() =>
{
var obj = MyObject as Test;
Console.WriteLine("3: " + obj.MyValue);
Thread.Sleep(100);
Update("Thread2");
Console.WriteLine("4: " + obj.MyValue);
});
void Update(string val)
{
lock (MyObject)
{
MyObject.MyValue = val;
}
}
Thread.Sleep(400);
Console.WriteLine("5: " + MyObject.MyValue);
}
}
class Test
{
public string MyValue { get; set; }
}
运行上面的行,我得到这个输出
1:
2: Thread1
3:
4: Thread2
5: Thread2
我的期望是“3:”应该总是说“3:Thread1”,因为同一个对象之前已经更新过。但事实并非如此,我不确定我在这里错过了什么。。。有人能解释一下吗
只是一张小纸条。。。如果您运行代码并得到不同的顺序,请重新运行它。。。我只对上面的顺序感兴趣。有几件事:
Update()
方法将写入同步到MyValue
属性,但对读取不做任何操作。因此,运行时可以自由地为对象使用缓存值。这不太可能与您观察到的输出有关,因为实际上您不太可能看到这一点,尤其是在x86硬件上。但是控制台
类具有同步功能,以确保多个线程的一致输出,但代码中没有任何内容可以确保如果输出行按特定顺序写入,则导致这些输出行的代码(例如读取MyValue
属性)发生的顺序与这些输出行的显示顺序相同“3:
行之前显示了“2:
行,这实际上并不意味着对更新(“Thread1”)
的调用发生在对控制台.WriteLine(“3:+obj.MyValue”)的调用之前代码>
如果要确保输出行与程序中语句的执行顺序相匹配,还需要使用lock
语句来保护各个操作
更具体地,考虑以下代码的执行顺序:
thread 1 thread 2
-------- --------
"value" parameter <= "3: " + obj.MyValue
Console.WriteLine("1: " + obj.MyValue);
Update("Thread1");
Console.WriteLine("2: " + obj.MyValue);
Console.WriteLine(value);
请注意,您需要在每次调用Console.WriteLine()
时都使用该选项。这将确保写入控制台的任何值都是调用时属性的最新值。为什么您认为3应该说“Thread1”?它有效地与你的第一个线程同时运行,并且你在读取MyValue时没有相互排斥。你能更具体一点吗。。。“互斥”是什么意思?实例化引用MyObject
的新obj
实例的原因是什么?@RufusL:代码不会实例化新实例。它只是将对象引用复制到obj
局部变量中。我同意这有点奇怪,但它应该对程序操作没有影响。@PeterDuniho是的,我想我的意思是“创建对同一实例的新引用”。我也不知道这会对程序产生什么影响,这就是为什么我想知道它的用途。你能给我看一个代码示例吗?根据你的观点,你会如何编写代码?
lock (MyObject) Console.WriteLine("1: " + obj.MyValue);