2015-09-16 103 views
5

我很難理解爲什麼多線程失敗線程完成之前更新值。單獨的線程是否有自己的引用或值的副本?
多線程問題,更新的價值

如果不是這樣,我的理解下面的代碼應能正常工作時的MyMethod被調用,但通常不會在thread.IsAlive之前創建數組中的一些的MyType對象的實例爲假:

class MyClass 
{ 
    static MyType[] obj = new MyType[Environment.ProcessorCount - 1]; 
    void MyMethod() 
    { 
     Thread[] threads = new Thread[Environment.ProcessorCount - 1]; 

     for (int i = 0; i < Environment.ProcessorCount - 1; i++) 
     { 
      threads[i] = new Thread(() => FillObjects(i)); 
      threads[i].Priority = ThreadPriority.AboveNormal; 
      threads[i].Start(); 
     } 

     while (threads[i].Any(c => c.IsAlive)) 
     { 
      Thread.Sleep(50); 
     } 
    } 
    void FillObjects(int i) 
    { 
     obj[i] = new MyType(); 
     //perform actions with obj[i] to fill it with necessary values 
    } 
} 

回答

6

您需要循環變量的值賦給一個局部變量。否則,它可能是i在遞增經過這麼FillObjects(0)不會被調用,因此obj[0]從未分配的FillObjects(i)第一次執行時執行。

void MyMethod() 
{ 
    Thread[] threads = new Thread[Environment.ProcessorCount - 1]; 

    for (int i = 0; i < Environment.ProcessorCount - 1; i++) 
    { 
     int local = i; 
     threads[i] = new Thread(() => FillObjects(local)); 
     threads[i].Priority = ThreadPriority.AboveNormal; 
     threads[i].Start(); 
    } 

    while (threads.Any(c => c.IsAlive)) 
    { 
     Thread.Sleep(50); 
    } 
} 
+2

好點。如果'FillObjects()'中的第一個語句是'Thread.Sleep(1000)',可能只有'obj [Environment.ProcessorCount - 1]'是非空的,因爲循環會將'i'增加到它的最終值在創建第一個對象之前。考慮一下,FillObjects()可能會拋出,因爲在循環退出之前'i'實際上會增加到'Environment.ProcessorCount-1',因此超出了'obj'的範圍。 –

+0

感謝您的回覆,確實這是主要問題之一,現在它正確地實例化對象。然而,線程在關閉之前並未完全正確地完成所有操作,而是隨機執行此操作。有什麼建議麼? – Almis

+0

我發現自己的邏輯錯誤,現在它正常工作。 – Almis

-1

在多處理器機器上(必須具有的)結果寫入一個線程中的內存位置可能由於高速緩存而在另一個線程中不可見。使用Thread.VolatileReadThread.VolatileWrite讀取以讀取和寫入「通過」高速緩存。

參看the chapter on threading in c# 3.0 in a Nutshell作出解釋。 (查找問題「是否有可能在等待的方法來寫‘假’?」。這個例子基本上是你的情況。)

+0

出於好奇:什麼是錯的或不適用我說的? –

+0

雖然不是那個downvoted的人:我想不出使用volatileRead/Write來解決上述問題的場景。從簡單的恕我直言的C#引用的問題不符合上述問題,以及我沒有看到任何緩存問題,揮發性將解決。 – Linky

+0

@Linky Hm。這是兩個線程都訪問一個靜態變量。一個線程「已經寫入」(由該線程後面的事件表示)。另一個線程從寫入線程的角度讀取已寫入的值,但看不到寫入。在我看來,這很像這裏的場景。 –