通常講到平行運算,情況可能是有一大筆的資料,各筆並不相關且可獨立處理,所以利用CPU或GPU的核心同時做計算。但有一種情況是,我用平行的方式或使用執行緒去處理資料,會存取到共用的變數,那實際這是並行運算。

這邊先示範一個最簡單的例子:

int total = 0;
List<int> list = new List<int>
{
    1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
};
Parallel.ForEach(list, i =>
{
    Interlocked.Add(ref total, i);
    Console.WriteLine(i);
});

正常情況下,如果直接對 total 這變數做運算,最後的值一定不正確,而使用Interlocked來做加減,就可以確保 thread safe。

而解決並行運算的另一種方式,算是老方法了,即使你真的沒什麼關注新技術,這個方法你也一定會,就是使用lock語法:

lock(lockObj)
{
    TestSum++;
}

當然,有的人會覺得這方法效率較差,但影響的程式碼比較多時,用 lock 語法包起來是比較保險。當然還有另一種方式,是用前面提的Interlocked來達成:

private static int locked = 0;
public int TestSum { get; set; } = 0;

public void TestLock()
{
    bool flag = true;
    while (flag) 
    {
        if (0 == Interlocked.Exchange(ref locked, 1))
        {
            TestSum += 1;
            //release
            flag = false;
            Interlocked.Exchange(ref locked, 0);
        }
        else
        {
            Console.WriteLine("locked");
        }
    }
}

當然這部份寫法有點麻煩,最快的方式還是用 lock 語法。

參考資料