本文介绍了凡在此代码片段中的竞争条件吗? (从C#5.0中果壳)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是来自约瑟夫·阿尔巴哈里在一本坚果书中的优秀的C#5.0

This is from Joseph Albahari's excellent C# 5.0 in a Nutshell book

在他的一章中,他提到这个代码块中的一个竞争条件因为他没有麻烦地指定它在哪里,但运行代码多次我无法产生所述的竞争条件

In one of his chapters, he mentions a race-condition in this code block ..my guess is it's meant to be pretty self-evident, as he didn't bother to specify where it was but running the code multiple times I was unable to produce the said-race condition

_button.Click += (sender, args) =>
{
   _button.IsEnabled = false;
   Task.Run (() => Go());
};

void Go()
{
    for (int i = 1; i < 5; i++)
    {
        int result = GetPrimesCount (i * 1000000, 1000000);
        Dispatcher.BeginInvoke (new Action (() =>
       _results.Text += result + " primes between " + (i*1000000) + " and " +
                                   ((i+1)*1000000-1) + Environment.NewLine));
    }

    Dispatcher.BeginInvoke (new Action (() => _button.IsEnabled = true));
}


推荐答案

我不同意@塞尔的回答。你甚至不需要多个线程来查看问题。尝试运行您的代码的原始形式,并注意输出。对我来说,它是以下和有时是随机的(我固定第一个值):

I don't agree with @Serge's answer. You don't even need multiple threads to see the problem. Try to run your code in its original form and notice the output. For me it's the following and is sometimes random (I fixed the first value):

1000000 primes between 5000000 and 5999999
1000000 primes between 5000000 and 5999999
1000000 primes between 5000000 and 5999999
1000000 primes between 5000000 and 5999999


b $ b

注意最后两个值。他们都是一样的,但他们应该依赖 i 。问题不在于操作不是原子操作,因为GUI线程将按顺序执行操作。

Notice the last 2 values. They're all the same, but they should depend on i. The problem is not that the operation is not atomic, because the GUI thread will execute the actions sequentially anyway.

发生这种情况的原因是lambda函数传递给 BeginInvoke 在执行时不采用 i 的值 ,所以他们将在执行时看到 i 的最后一个值。解决方案是将 i 作为参数显式传递给lambda,如下所示:

The reason for this occurring is that the lambda function passed to BeginInvoke takes the value of i at the moment of execution, not at the moment of initialization, so they will all see the last value of i by the time they get executed. The solution is to explicitly pass i as a parameter to the lambda like so:

for (int i = 1; i < 5; i++)
{
    int result = 1000000;
    Dispatcher.BeginInvoke(new Action<int>(j =>
    results.Text += result + " primes between " + (j * 1000000) + " and " +
                              ((j + 1) * 1000000 - 1) + Environment.NewLine), i);
}

这篇关于凡在此代码片段中的竞争条件吗? (从C#5.0中果壳)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-16 06:51