2014-02-14 126 views
0

我写了这个控制台程序:如何同步多线程

static void Main(string[] args) 
{ 
    object sync = new object(); 
    Thread[] t = new Thread[10]; 
    int count = 0; 

    for (var i = 0; i < t.Length; i++) 
    { 
     t[i] = new Thread(() => 
     { 
      lock (sync) 
      { 
       int inc = count; 
       Console.WriteLine("Count: {0}", count); 
       count = inc + 1; 
      } 
     }); 
    } 

    foreach (var t1 in t) 
    { 
     t1.Start(); 
    } 

    foreach (var t1 in t) 
    { 
     t1.Join(); 
     Console.WriteLine("\nFinal Count= {0}", count); 
     Console.ReadKey(); 
    } 
} 

我得到这样的结果输出:

Count: 0 
Count: 1 
Count: 2 
Count: 3 
Count: 4 
Count: 5 
Count: 6 
Count: 7 

Final Count= 7 
Count: 8 
Count: 9 

,当我运行多个应用程序时,我得到更多的不同的结果 ,但我希望看到这样的结果:

Count: 0 
Count: 1 
Count: 2 
Count: 3 
Count: 4 
Count: 5 
Count: 6 
Count: 7 
Count: 8 
Count: 9 

Final Count= 10 

为什么它返回不同的resul我如何解决这个问题?

+0

'数= INC + 1它们同步;'变得毫无意义。张贴实际的代码。 –

+0

“最终计数”是可以实现的,但如果你想要数字,那么就不要使用线程。 –

回答

1

好,而不是这样的:

foreach (var t1 in t) 
{ 
    t1.Join(); 
    Console.WriteLine("\nFinal Count= {0}", count); 
    Console.ReadKey(); 
} 

你应该写:

foreach (var t1 in t) 
{ 
    t1.Join(); 

} 
Console.WriteLine("\nFinal Count= {0}", count); 
Console.ReadKey(); 

否则,你将有一个赛车和你的代码将undeterministic。

+0

事实上 - 随着原始代码的写入,只要检测到任何一个线程完成,就会显示“最终计数”。实际上,我很惊讶“最终计数”消息只出现一次,因为我期望每个线程都会看到一次... –

+0

这将是如此,但他在循环内有Console.ReadKey() 。 –

+0

当然 - 该计划甚至没有运行完成。 \ * facepalm \ * –

2

尽量不要手动创建/终止这样的线程,这是一个耗时的操作,它不能很好地扩展。使用ThreadPool代替。

或者更好的使用任务,利用await Task.WhenAll(list of your tasks)

+0

没那么快。这显然是“演示”代码,它取决于稍后将在实际线程中执行什么。 –

+0

@HenkHolterman我明白你的意思(它是有效的),但我仍然会推荐任务而不是线程。除非OP提供了有关线程为什么比任务更好的信息(长时间运行的操作等),否则任务将提供更简单的方法来同步执行。 – ken2k