假设我有两个线程,线程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/ReaderWriterLockSlimMutexSemaphore等)。

关于c# - C#Getter-Setter竞赛条件,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/11974560/

10-13 02:53