并行任务对共享变量的处理

本文关键字:处理 共享变量 并行任务 | 更新日期: 2023-09-27 18:29:29

我从任务库开始。我写了像这样的简单代码

private void button1_Click(object sender, EventArgs e)
{
    simpleMost();
}
string mesg;
void simpleMost()
{
    mesg = "";
    button1.Enabled = false;
    Task t1 = new Task(delegate { makeResult(1); });
    Task t2 = new Task(delegate { makeResult(2); });
    Task t3 = new Task(delegate { makeResult(3); });
    t1.Start();
    t2.Start();
    t3.Start();
    t1.Wait();
    t2.Wait();
    t3.Wait();
    richTextBox1.Text = mesg;
    button1.Enabled = true;
}
void makeResult(int a)
{
    mesg += "'nTask" + a;
}

我一次又一次地点击我的按钮1,得到以下输出

1.

Task3
Task1
Task2

2.

Task1
Task2
Task3

3.

Task1
Task2
Task3

4.

Task2
Task3

5.

Task1
Task3

6.

Task1
Task2

在4、5、6种情况下,为什么makeResult不能正常工作。当我检查等待语句后的任务状态时,发现它们都已完成,但其中一个未正确执行传递给它的函数

并行任务对共享变量的处理

您有几个任务,每个任务都以非原子的方式修改相同的共享资源。

mesg += "'nTask" + a;

是有效的:

mesg = mesg + "'nTask" + a;

因此,如果一个任务读取mesg,那么另一个任务将向其写入一个新值,那么第一个任务将使用旧值连接字符串,并将其写回变量。

避免这种情况的最简单方法是使用锁定,这样一次只有一个线程可以执行修改语句。它并不像可能的那样优雅,但它应该会消除你目前的比赛条件。

我认为有时两个任务试图同时访问"mesg"。用锁试试。

object syncObject = new object();
void makeResult(int a)
{
    lock (syncObject)
    {
        mesg += "'nTask" + a;
    }
}