2015-02-07 155 views
0

本課程使用lockInterlockedc#鎖不能按預期工作

increaseCount.with_lock.Run();increaseCount.with_interlock.Run();都在96-100之間打印。

我期待他們兩人始終打印100.我犯了什麼錯誤?

public static class increaseCount { 
    public static int counter = 0; 
    public static readonly object myLock = new object(); 
    public static class with_lock { 
     public static void Run() { 
      List<Thread> pool = new List<Thread>(); 
      for(int i = 0; i < 100; i++) { 
       pool.Add(new Thread(f)); 
      } 
      Parallel.ForEach(pool, x => x.Start()); 
      Console.WriteLine(counter); //should print 100 
     } 

     static void f() { 
      lock(myLock) { 
       counter++; 
      } 
     } 
    } 

    public static class with_interlock { 
     public static void Run() { 
      List<Thread> pool = new List<Thread>(); 
      for(int i = 0; i < 100; i++) { 
       pool.Add(new Thread(f)); 
      } 
      Parallel.ForEach(pool, x => x.Start()); 
      Console.WriteLine(counter);//should print 100 
     } 

     static void f() { 
      Interlocked.Add(ref counter, 1); 
     } 
    } 
} 
+0

你的代碼沒問題。唯一的問題是你的期望。基本上,並不是所有的100個線程都能運行,直到顯示計數器。嘗試在Console.WriteLine(counter)之前放置一個Thread.Sleep(1000),你會明白我的意思。 – 2015-02-07 23:39:56

+0

@everyone謝謝 – 2015-02-07 23:59:55

回答

4

在這兩種情況下,你開始你的線程,但你不要等到他們完成這樣你就不會達到100打印結果和應用程序關閉之前。

如果你開始的所有線程,你會等待之後,所有這些線程與Thread.Join完成,你總是會得到正確的結果:

List<Thread> pool = new List<Thread>(); 
for (int i = 0; i < 100; i++) 
{ 
    pool.Add(new Thread(f)); 
} 

Parallel.ForEach(pool, x => x.Start()); 
foreach (var thread in pool) 
{ 
    thread.Join(); 
} 

Console.WriteLine(counter); 

注:這似乎是某種形式的測試,但你應該知道阻止多個線程在一個單一的lock是一個巨大的資源浪費。

1

我認爲這是因爲你的Parallel.Foreach調用只是調用pool中的所有線程上的開始,但是在循環結束和調用Console.WriteLine時它們不一定完成。如果您要在Console.WriteLine之前插入Thread.Sleep(5000); // 5s sleep或類似文字,它可能會始終打印出您期望的內容。

1

你的代碼沒問題。唯一的問題是你的期望。基本上,並不是所有的100個線程都能運行,直到顯示計數器。嘗試在Console.WriteLine(counter)之前放置一個Thread.Sleep(1000),你會明白我的意思。

編輯:錯誤地發表評論第一次。