1 回答
TA贡献1828条经验 获得超13个赞
有几件事:
您的
Update()
方法将写入同步到属性MyValue
,但对读取不执行任何操作。因此,运行时可以自由地使用对象的缓存值。这不太可能与您观察到的输出有任何关系,因为实际上您不太可能看到这一点,尤其是在 x86 硬件上。但…更重要的是,您的代码所展示的只是输出顺序可能会产生误导。该类
Console
具有同步功能以确保来自多个线程的一致输出,但是代码中没有任何内容可以确保如果按特定顺序写入输出行,则导致这些输出行的代码(例如读取属性)MyValue
发生与这些输出行的显示顺序相同。
换句话说,仅仅因为控制台"2:"
在该行之前显示了该行"3:"
,实际上并不意味着对的调用发生Update("Thread1")
在对Console.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()即,在第一个线程开始其逻辑之前,第二个线程计算传递给的参数是完全合法的。但是,第一个线程也可以在第二个线程有机会实际调用该Console.WriteLine()方法之前抢占第二个线程。
如果发生这种情况,您会看到线程 1 的预期输出顺序,但线程 2 的输出写入该属性的明显过时版本MyValue,因为它是在线程 1 运行其任何逻辑之前检索到的。
为了解决该特定场景,您可以使用lock呼叫WriteLine()。例如:
lock (MyObject) Console.WriteLine("1: " + obj.MyValue);
请注意,您需要将其放在每次调用Console.WriteLine(). 这将确保写入控制台的任何值都是调用时属性的最新值。
- 1 回答
- 0 关注
- 91 浏览
添加回答
举报