2013-12-14 30 views
0

我正在嘗試自學自己的過程在c#中線程化,我一直在閱讀大量的教程,問題和示例。我已經成功地(*它似乎工作)實現了線程到更大的應用程序,但它們是一些對我來說很灰暗的地方。線程和線程安全 - 如何管理數據進出線程

我試圖把一個小的控制檯應用程序放在一起作爲討論的焦點,並嘗試回答提出的問題。我不是一個有經驗的程序員 - 所以如果我在這裏犯了一些致命的罪行,我真誠道歉。隨意指出,以提高我的編程技能。希望我在這裏提出的問題能夠幫助我和其他人嘗試理解線程化。

  1. 第一個問題是 - 如果我叫 randomNums.GenrateRandomNumbers()內的ThreadStart(),將在該 被認爲是不安全的。我得出結論,它會是 PrintRandomCNumbers()正在從其他線程調用,它會意味着對象將處於非常未確定的狀態?

  2. 如果我想打電話給randomNums.GenrateRandomNumbers,那麼線程安全的方式是什麼?如何以及在哪裏實施 鎖定,我會使用寫入多重讀鎖嗎?

  3. 當運行該應用程序,每個線程正確輸出randomNums的 內容,是有一個方案(多個處理器或核 ),其中給定的這種實現中的信息將不會 存在以輸出,但拷貝的對象引用仍然在 範圍內。即randomNums變爲null。

  4. 如果沒有硬件方案,我將如何處理這個 示例來生成這樣的場景。即Threadmanger擁有 Randomnums對象引用,但它只是最終指向 未啓動對象,但嘗試啓動該對象。 (在我的更大的應用程序中,我有一個 類似的問題。)

  5. 什麼是使數據進出 線程的最佳設計實踐?

  6. 當設計一個線程來啓動時,最好的做法是管理對象內部或對象外的線程的開始和頂部。


using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
// Using System Threading for theads; 
using System.Threading; 

namespace ThreadingExamples 
{ 
    class Program 
    { 

     static void Main(string[] args) 
     { 
      MyApplication app = new MyApplication(); 
      app.Start(); 
     } 


     public class MyApplication 
     { 
      private RandomNumbers randomNums; 


      public MyApplication() 
      { 

      } 

      public void Start() 
      { 
       randomNums = new RandomNumbers(); 
       randomNums.GenrateRandomNumbers(); 
       randomNums.PrintRandomcNumbers(); 

       ThreadManager newThreadMan = new ThreadManager(randomNums); 

       Console.ReadLine(); 
      } 

     } 

     public class ThreadManager 
     { 
      private RandomNumbers randomNums; 
      private Thread[] newThreads; 
      private int threadCount; 

      public ThreadManager(RandomNumbers newRandomNums) 
      { 
       threadCount = 3; 
       randomNums = newRandomNums; 
       newThreads = new Thread[threadCount]; 
       for (int i = 0; i < threadCount; i++) 
       { 
        newThreads[i] = new Thread(ThreadStart); 
        newThreads[i].Start(); 
       } 
      } 
      public void ThreadStart() 
      { 
       randomNums.PrintRandomcNumbers(); 
      } 

     } 

     public class RandomNumbers 
     { 
      private Random rnd = new Random(); 
      private int numberToStore; 
      private int[] randomNumbers; 

      public RandomNumbers() 
      { 
       numberToStore = 12; 
       randomNumbers = new int[numberToStore]; 
      } 

      public void GenrateRandomNumbers() 
      { 
       for (int i = 0; i < numberToStore; i++) 
       { 
        randomNumbers[i] = rnd.Next(1,13); 
       } 
      } 
      public void PrintRandomcNumbers() 
      { 
       StringBuilder outputString = new StringBuilder(); 
       for (int i = 0; i < numberToStore; i++) 
       { 
        outputString = new StringBuilder("The Random Numbers in position "); 
        outputString.Append(i.ToString()); 
        outputString.Append("is the number: "); 
        outputString.Append(randomNumbers[i].ToString()); 

        Console.WriteLine(outputString); 
       } 
      } 
     } 
    } 
} 
+4

只問一個問題。你無法從SO問題中學習線程,有很多優秀的書籍可用。 –

+0

好的學習線程在SO旁邊,我試着把一些問題集中到一點,而不是一個開放式問題。 –

+0

請閱讀[問]。 –

回答

1
  1. 書面隨機數的調用是足夠實際上安全的,不好的做法,因爲隨機數將改變基於線程的時候執行的,有事要記住這裏,如果要在每個線程中存儲更改的數字,比如說一個是6,另一個線程的數目是12,那麼這兩個線程都會有一個隨機數列表,其中包含12個數字,而具有6個數字的隨機數字只會更改第一個列表中有6個元素,而不是調整列表本身的大小。

  2. 如何從內部線程安全地更改數據的簡單解釋是不要。我實際上會找到一種不同的方式來做到這一點。如果您發現自己需要在每個線程中顯示不同的隨機數字,例如生成不同的列表並將其傳遞給線程。

  3. 由於你沒有實例化一個新的對象,因爲這個程序可以正常工作,數據可能並不完全符合你的期望,但是不存在數據不會在那裏的情況。

  4. 實際上,這將很容易強制失敗,每次調用GenerateRandomNumbers函數時都會簡單實例化一個新列表。這可能會導致運行時問題,當一個線程處於循環中的位置時,它會生成一個新列表,而另一個線程正在尋找該列表中的項目7,但由於新列表未初始化,因此不在此處。

    public void GenrateRandomNumbers() 
        { 
         randomNumbers=new List<int>(); 
         for (int i = 0; i < numberToStore; i++) 
         { 
          randomNumbers[i] = rnd.Next(1,13); 
         } 
        } 
    
  5. 有一個問題我已經找到使用線程時,是讓所有的物品一成不變的東西,這就省去了要小心,在一個線程重新分配值,因爲簡單地說不能做。這確實會導致您必須考慮如何在不改變價值的情況下完成您試圖完成的任務,但這實際上是一種編程的好方法,並且會使您的線程體驗更好。

  6. 線程本質上是一個消防和忘記程序,它執行和執行它自己的事情,無論它在何處或什麼時候被調用,並且能夠與所有正在運行的程序進行交互。既然這是真的,那麼你在哪裏開始線程並不重要,重要的是該線程如何與你正在運行的任何東西進行交互。我總是發現使用線程時的最佳做法是,當你絕對必須執行線程時。要做一個多線程應用程序,你應該計劃在設計階段使它成爲多線程。仔細想想每個線程應該做什麼,並始終注意它將如何與其他正在運行的線程交互。

+0

謝謝你的見解。乾杯。 –