多執行緒學習(二)

Heliooo發表於2019-06-24

  向執行緒傳遞引數
  程式碼中實現了三種不同的方法向執行緒中傳遞引數。
 

 1 /*-----------------------------------------------------------------------
 2                         written by helio, 2019
 3                             ThreadSample3
 4 -----------------------------------------------------------------------*/
 5 using System;
 6 using System.Threading;
 7 
 8 namespace ThreadSample
 9 {
10     class Program
11     {
12         static void Main(string[] args)
13         {
14             var sample = new ThreadSample(10);
15 
16             var ThreadOne  = new Thread(sample.CountNumbers);
17             ThreadOne.Name = "ThreadOne";
18             ThreadOne.Start();
19             ThreadOne.Join();
20             Console.WriteLine("------------------------");
21 
22             var ThreadTwo = new Thread(Count);
23             ThreadTwo.Name = "ThreadTwo";
24             ThreadTwo.Start(8);
25             ThreadTwo.Join();
26             Console.WriteLine("------------------------");
27 
28             var ThreadThree = new Thread(() => CountNumbers(12));
29             ThreadThree.Name = "ThreadThree";
30             ThreadThree.Start();
31             ThreadThree.Join();
32             Console.WriteLine("------------------------");
33 
34             int i = 10;
35             var ThreadFour = new Thread(() => PrintNumber(i));
36             i = 20;
37             var ThreadFive = new Thread(() => PrintNumber(i));
38             ThreadFour.Start();
39             ThreadFive.Start();
40 
41             Console.ReadKey();
42         }
43 
44         static void Count(object iterations)
45         {
46             CountNumbers((int)iterations);
47         }
48         
49         static void CountNumbers(int iterations)
50         {
51             for (int i = 1; i <= iterations; i++)
52             {
53                 Thread.Sleep(TimeSpan.FromMilliseconds(0.5));
54                 Console.WriteLine("{0} prins {1}",
55                     Thread.CurrentThread.Name, i);
56             }
57         }
58 
59         static void PrintNumber(int number)
60         {
61             Console.WriteLine(number);
62         }
63 
64         class ThreadSample
65         {
66             private readonly int m_iterations;
67 
68             public ThreadSample(int iterations)
69             {
70                 m_iterations = iterations;
71             }
72             public void CountNumbers()
73             {
74                 for (int i = 1; i <= m_iterations; i++)
75                 {
76                     Thread.Sleep(TimeSpan.FromSeconds(0.5));
77                     Console.WriteLine("{0} prints {1}",
78                         Thread.CurrentThread.Name, i);
79                 }
80             }
81         }
82     }
83 }

  工作原理
   方法一:
    當主程式啟動時,首先建立了ThreadSample類的一個物件,並提供了一個迭代次數。然後使用該物件的CounetNumbers方法啟動執行緒。該方法執行在另一個執行緒中,但是使用數字10,該數字是通過ThreadSample物件的建構函式傳入的。
  方法二:
    另一種傳遞資料的方式是使用Thread.Staru方法。該方法會節後一個物件,並將該物件傳遞給執行緒。為了應用該方法,線上程啟動的方法必須接收object型別的單個引數。
  方法三:
    接下來的方式是使用lambda表示式。這可能會導致幾個問題。例如,如果在多個lanbda表示式中使用相同的變數,他們會共享該變數。當啟動ThreadFour和ThreadFive執行緒時,他們都會列印20,因為在這兩個執行緒啟動之前變數被修改為20。

執行緒鎖
  為什麼要用執行緒鎖?
  所謂同步,是指多個執行緒之間存在先後執行的順序的關聯關係。如果一個執行緒必須在兩一個執行緒完成某個工作後才能繼續執行,則必須考慮如何讓讓其保持同步,以確保在系統上同時執行多個執行緒而不會出現死鎖或邏輯錯誤。

 1 /*-----------------------------------------------------------------------
 2                         written by helio, 2019
 3                             ThreadSample4
 4 -----------------------------------------------------------------------*/
 5 using System;
 6 using System.Threading;
 7 
 8 namespace LockSample1
 9 {
10     class Program
11     {
12         static void Main(string[] args)
13         {
14             Thread[] threads = new Thread[10];
15             Account acc = new Account(1000);
16             for (int i = 0; i < 10;i++)
17             {
18                 Thread t = new Thread(acc.AutoWithdraw);
19                 t.Name = "Thread" + i;
20                 threads[i] = t;
21             }
22 
23             for (int i = 0; i < 10; i++)
24                 threads[i].Start();
25             Console.ReadKey();
26         }
27 
28         class Account
29         {
30             private Object lockedObj = new object();
31             private int m_balenace;
32             Random r = new Random();
33             public Account(int initial)
34             {
35                 m_balenace = initial;
36             }
37 
38             public int Withdraw(int amount)
39             {
40                 Thread.Sleep(TimeSpan.FromMilliseconds(100));
41                 if (m_balenace < 0)
42                 {
43                     Console.WriteLine("餘額不足!");
44                 }
45 
46                 lock (lockedObj)
47                 {
48                     if (m_balenace >= amount)
49                     {
50                         Console.Write("{0}取款---取款前餘額:{1} 取款 {2}    ", Thread.CurrentThread.Name, m_balenace, amount);
51                         m_balenace -= amount;
52                         Console.WriteLine("取款後餘額:{0}", m_balenace);
53                         return amount;
54                     }
55                     else
56                     {
57                         return 0;
58                     }
59                 }
60             }
61 
62             public void AutoWithdraw()
63             {
64                 for (int i = 0; i < 100; i++)
65                 {
66                     Withdraw(r.Next(1, 100));
67                 }
68             }
69         }
70     }
71 }

閱讀原文可訪問我的個人部落格

相關文章