对并行更新变量感到困惑

本文关键字:变量 并行 更新 | 更新日期: 2023-09-27 18:04:55

我是c#新手,有一个问题想问你。关于"并行更新变量"的问题

我的代码如下:

private void Form1_Load(object sender, EventArgs e)
{
    Control.CheckForIllegalCrossThreadCalls = false;
    // ---------------------------
    Thread tTrue = new Thread(new ThreadStart(TrueThread));
    tTrue.Start();
    Thread tFalse = new Thread(new ThreadStart(FalseThread));
    tFalse.Start();
}
bool Start = false;
bool value;
void TrueThread()
{
    while (true)
    {
        if (Start == true)
        {
            value = true;
            break;
        }
    }
}
void FalseThread()
{
    while (true)
    {
        if (Start == true)
        {
            value = false;
            break;
        }
    }
}
private void button1_Click(object sender, EventArgs e)
{
    MessageBox.Show(value.ToString());
}
private void button2_Click(object sender, EventArgs e)
{
    Start = true;
}

代码解释:首先,当我的应用程序启动->调用TrueThread和谬误线程当TrueThread和false thread启动时,它们将检查"start"值,当start变量变为"true"时(默认为false,当我点击按钮2时将设置为true), TrueThread将设置"value"变量为true,而false thread将设置"value"变量为false。

但我困惑,哪个线程将首先运行?"value"的最终值是真还是假?为什么?

点击button1查看结果

对并行更新变量感到困惑

如果没有适当的同步,就无法对您的问题给出明确的答案。除非您同步访问共享变量并提供特定的执行顺序,否则您无法知道哪个线程将首先运行,哪个线程将首先完成其工作(即使它们具有像示例中那样简单的主体)。这意味着您无法可靠地预测value变量的最终值。

相同的代码在不同的硬件上,在不同的Windows主要(和次要)版本上,或者实际上,在相同的硬件上,但在不同的时间运行(取决于系统正在处理多少负载等)

这就是同步原语(如临界区、互斥锁等)存在的原因:协调多个线程的工作,并在利用并行处理的同时可靠地预测最终结果。

在更复杂的程序中,可以在多个线程中设置共享变量(如代码中的value),如果不同步线程,可能会导致无效状态。

考虑这个(相当简单的)例子:

// thread 1
value = true;
// ...
if ( value == true )
{
    // #1: at this point, thread 1 may get suspended; go to #2
    // do something critical
}
// thread 2
if ( value == false )
{
    // do something mutually exclusive, also critical
    // #3: if value got changed to false  after thread 1 enters the 'if'
    // this code will also execute, even though it's mutually exclusive;
    // we reached a bad state
}
// thread 3
// #2: if this runs just at the "right" time, 'value' gets overwritten
// while thread 1 is already inside the 'if'; go to #3
value = false;

因为你不能准确地告诉value何时被设置为truefalse,你不能保证只有一个重要的任务将被执行。你必须同步访问value,以确保一旦一个线程设置了它的值,其他线程看到的是最新的值,而不是中间的值。

无可否认,这个例子有点做作,但它确实说明了没有正确同步的一个可能的问题(许多问题)。(在这种简单的情况下,使用lock可以解决问题。还有一些特定的数据结构,如BlockingCollectionConcurrentDictionary等,用于提供跨多个线程对各种数据结构的安全访问。