编程语言
首页 > 编程语言> > c#-使用Parallel.Invoke和静态变量时的怪异行为

c#-使用Parallel.Invoke和静态变量时的怪异行为

作者:互联网

我正在尝试测试C#并行方法,这是我的测试程序:

class Program
{
    static int counter;
    static void Main(string[] args)
    {
        counter = 0;
        Parallel.Invoke(
            () => func(1),
            () => func(2),
            () => func(3)
            );
        Console.Read();
    }


    static void func(int num)
    {
        for (int i = 0; i < 5;i++ )
        {
            Console.WriteLine(string.Format("This is function #{0} loop. counter - {1}", num, counter));
            counter++;
        }
    }
}

我试图做的是拥有1个静态共享变量,每个函数实例会将其增加1.

我希望计数器将按顺序打印(1,2,3,…)
但是输出令人惊讶:

This is function #1 loop. counter - 0
This is function #1 loop. counter - 1
This is function #1 loop. counter - 2
This is function #1 loop. counter - 3
This is function #1 loop. counter - 4
This is function #3 loop. counter - 5
This is function #2 loop. counter - 1
This is function #3 loop. counter - 6
This is function #3 loop. counter - 8
This is function #3 loop. counter - 9
This is function #3 loop. counter - 10
This is function #2 loop. counter - 7
This is function #2 loop. counter - 12
This is function #2 loop. counter - 13
This is function #2 loop. counter - 14

谁能向我解释为什么会这样?

解决方法:

问题是您的代码不是线程安全的.例如,可能发生的情况是:

>函数2获取计数器的值以在Console.WriteLine()中使用它
>函数1获取计数器的值,调用Console.WriteLine(),使计数器递增
>函数1获取计数器的值,调用Console.WriteLine(),使计数器递增
>函数#2最终使用旧值调用Console.WriteLine()

另外,它本身也不是线程安全的,因此最终值可能不是15.

要解决这两个问题,可以使用Interlocked.Increment()

for (int i = 0; i < 5; i++)
{
    int incrementedCounter = Interlocked.Increment(ref counter);
    Console.WriteLine("This is function #{0} loop. counter - {1}", num, incrementedCounter);
}

这样,您将获得增量后的数字,而不是原始代码中的数字.同样,此代码仍不会以正确的顺序打印数字,但是您可以确保每个数字将被打印一次.

如果确实要按正确的顺序排列数字,则需要使用锁:

private static readonly object lockObject = new object();

…

for (int i = 0; i < 5; i++)
{
    lock (lockObject)
    {
        Console.WriteLine("This is function #{0} loop. counter - {1}", num, counter);
        counter++;
    }
}

当然,如果执行此操作,实际上不会获得任何并行性,但是我认为这不是您的真实代码.

标签:parallel-extensions,c
来源: https://codeday.me/bug/20191123/2066995.html