我正在尝试运行书中的以下程序。
作者声称结果输出 “应该是”
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/