假设我有两个线程,线程A和线程B。当线程A设置一个对象,将对象X命名为一个值,并且线程B出现并尝试获取该对象(由线程设置)时,在C#中会发生什么一种? C#会抛出异常,是B在A对其进行更改之前接收对象X,还是B在A对它进行更改之后接收对象X?
我以为很清楚,但是这里是代码(即使添加了同步,我仍然不是100%确信这会导致我上面提到的确切情况发生):
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace WindowsFormsApplication8 {
public partial class Form1 : Form {
private AutoResetEvent waitEvent = new AutoResetEvent(false);
int objectX = 0;
public Form1() {
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e) {
DateTime startTime = DateTime.Now;
Console.WriteLine("---------------------------- START @ " + startTime + " ----------------------------------------------------------------------");
Thread A = new Thread(ThreadAWorkMethod);
Thread B = new Thread(ThreadBWorkMethod);
objectX = 0;
waitEvent = new AutoResetEvent(false);
A.Start();
B.Start();
A.Join();
B.Join();
Console.WriteLine("---------------------------- FINISHED AFTER " + (DateTime.Now - startTime).TotalMilliseconds + " ----------------------------");
}
public void ThreadAWorkMethod() {
waitEvent.WaitOne();
objectX = 5;
Console.WriteLine("Value has been changed to: " + objectX + " in thread A at " + DateTime.Now);
return;
}
public void ThreadBWorkMethod() {
waitEvent.Set();
string xInThreadB = objectX.ToString();
Console.WriteLine("Value in thread B: " + xInThreadB + " at " + DateTime.Now);
return;
}
}
}
线程B向控制台的输出看起来是0或5,但是即使您仍然无法通过检查DateTime来确定哪个线程首先被服务,因为两个线程将具有相同的时间戳记……并且始终有一个输出使它成为时间戳。首先到控制台,以便说谁先得到服务,以及线程是否在获取集上实际发生冲突。因此,最后,就像某些人提到的那样,似乎是从较低的框架级别对C#中的变量实现了锁定。
最佳答案
不,可能不会。运行时中没有任何东西会自动检查这种情况并引发异常。
但是,此时设置的“值”可能处于有效状态,也可能不处于有效状态,因此,一旦使用结果,无论使用什么值,都很容易引发异常。
两者皆有可能。根据“对象”的类型,B也有可能接收到处于无效状态的对象。
如果您知道多个线程将访问一个值,则应始终注意同步对属性的访问。有许多同步选项,从使用(相对)简单的 lock
statement到其他更复杂的同步选项(例如ReaderWriterLock
/ReaderWriterLockSlim
,Mutex
,Semaphore
等)。
关于c# - C#Getter-Setter竞赛条件,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/11974560/