今天我們來講如何把一個程式多執行緒化。首先,多執行緒的程式需要有相對應的硬體支援,昨天講到說每個執行緒會被一個CPU的核心所執行,所以在硬體方面至少需要一個多核心的CPU,不然的話多個執行緒都給同個人執行,不會比較快反而會比較慢而已。
雖然前面把多個執行緒講的如此神奇,但實際做起來的時候會發現諸多限制、考量與麻煩。
Race Condition是一個我自己在寫多執行緒時常常遇到的問題,既然提到了mult-thread當然要說明一下,更可以體會我在上面所說的不方便。
舉一個非常簡單的例子,假設今天我想讓0這個數字被+1三次,最終的解答應該是3
如果是一個執行緒的情況應該會是這樣:
0 + 1 = 1
1 + 1 = 2
2 + 1 = 3
其中一次 +1 做的事情有三件
執行緒A拿取現在的數字 (0)
執行緒A把0+1 (0 + 1)
執行緒B拿取現在的數字 (0)
執行緒A把結果存回去(1)
執行緒C拿取現在的數字(1)
執行緒B把拿到的數字加一 (0 + 1)
執行緒C把拿到的數字加一 (1 + 1)
執行緒C把結果存回去(2)
執行緒B把結果存回去(1)
最後輸出的結果居然是1,因為沒辦法判斷哪個執行緒會先做後做,以及做到哪個階段,導致相互污染彼此的資料,這種情況就叫做Race condition。
還記得我第一次在寫multi-thread的經驗,那個時候在寫一支用來算遊戲佈局最佳化的程式,因為我選擇的最佳化演算法需要經過一輪一輪的迭代(基因演算法),一算下來可能會花上不少時間,造成我在校調演算法的過程中,改動幾個參數我要等上一個多小時才能夠觀測到結果,於是就導入了multi-thread 在我的程式中,那個時候使用的是openMP這個函式庫,把電腦的CPU用好用滿,速度快了4.6倍。