c# - C#中的多线程

标签 c#

我正在尝试运行书中的以下程序。

作者声称结果输出 “应该是”

1000

2000

....

10000

如果你在普通处理器上运行程序,但在多处理器计算机上,它可能是

999

1998

...

9998

当使用正常的增量方法(number+=1)但使用程序中所示的联锁增量解决问题时(即你得到第一个输出)

现在我有 3 个问题。 首先,为什么我不能在内循环中使用正常增量 [i++ 而不是 Interlocked.Increment(ref i)]。为什么作者选择了另一种方法?

其次,Thread.Sleep(1000) 在上下文中的目的是什么。当我注释掉这一行时,即使我使用 Interlocked 方法来增加数字,我也会得到第二个输出。

第三,如果我不注释 Thread.Sleep(1000) 行和第二个输出,即使我使用正常的增量方法 [number += 1] 也会得到正确的输出。

现在我正在 Intel(R) Core(TM) i7 Q820 cpu 上运行该程序,如果它有任何不同的话

static void Main(string[] args)
{
    MyNum n = new MyNum();

    for (int a = 0; a < 10; a++)
    {
        for (int i = 1; i <= 1000; Interlocked.Increment(ref i))
        {
            Thread t = new Thread(new ThreadStart(n.AddOne));
            t.Start();
         }            
        Thread.Sleep(1000);
        Console.WriteLine(n.number);
    }
}

class MyNum
{
    public int number = 0;
    public void AddOne() 
    {
        Interlocked.Increment(ref number);
    }
}

最佳答案

sleep 很容易——让线程完成,然后再查看结果。不过,这并不是一个很好的答案——虽然他们应该在一秒钟内完成,但不能保证他们确实做到了。

MyNum 类中对互锁增量的需求很明确——有 1000 个线程尝试获取数字,如果没有保护,一个人很可能先读取数字,然后第二个读取它,然后是第一个把它放回去,然后第二个把它放回去,抹掉第一个所做的改变。请注意,当有多个内核时,此类错误更有可能发生,否则只有在错误的时间触发线程切换时才会发生。

不过,我不明白为什么我需要受到保护。

编辑:您得到的结果大致相同,因为代码执行得太快了。线程运行速度比创建时快,因此它们不会同时运行。

尝试:

public void AddOne()
{
int x = number + fibnocci(20) + 1 - fibnocci(20);
}

private int fibnocci(int n)
{
if (n < 3) return 1 else return fibnocci(n - 1) + fibnocci(n - 2);
}

(我希望优化器不够好,无法杀死这些额外的代码)

关于c# - C#中的多线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4093659/

相关文章:

c# - Linq:对几个GroupBy的结果进行分组

javascript - 将数字数组从 ajax 传递到 Controller

c# - 将 Regex.Matches 连接到一个字符串

c# - 在 Linq to Entities 查询中编写 if then else

c# - 反序列化未知维度的锯齿状数组

c# - 创建字典<string, Dictionary<T, T[]>[]>

c# - 在列表 dataTemplate xaml 中绑定(bind)项目本身

c# - Microsoft AntiXSS - 是否需要解码?

c# - HTML Firefox 表格对齐问题

c# - 方法未从任务委托(delegate)中调用