在看十億行天文臺資料挑戰的時候發現不需要鎖,
研究之下發現,即使並行執行,也不一定需要鎖
Aggregate它本身是並行的,
同執行緒內就順序執行字典了,
非同執行緒會等待到結束並行之後再合併,
這樣是不需要鎖的.
如果不是末尾,那麼需要再次.AsParallel
var partialSums = numbers.AsParallel()
.Select(n => n * 2)
.Aggregate(0, (acc, n) => acc + n)
.AsParallel()
.Select(n => n / 2);
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
class Program
{
static void Main()
{
// 建立一個字串列表
List<string> words = new List<string> { "hello", "world", "linq", "parallel", "example" };
// 使用PLINQ並行處理列表
var uppercasedWords = words.AsParallel().Select(word => {
// 模擬一些處理,這裡只是簡單地將字串轉換為大寫
return word.ToUpper();
});
// 順序輸出結果
foreach (var word in uppercasedWords)
{
Console.WriteLine(word);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static void Main()
{
// 建立一個數字列表
List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
// 使用PLINQ並行處理列表
var processedNumbers = numbers.AsParallel()
.Select(n => n * 2) // 將每個數字翻倍
.Where(nn => nn % 2 == 0) // 篩選出偶數
.Select(x => x / 2); // 將篩選後的數字除以2
// 順序輸出結果
foreach (var number in processedNumbers)
{
Console.WriteLine(number);
}
}
}
var result = numbers.AsParallel()
.Select(n => n * 2)
.Aggregate(0, (acc, n) => acc + n);
在這個例子中,
.Aggregate() 方法會在
.Select(n => n * 2) 操作完成後開始執行,
並在所有元素處理完畢後合併結果。
.Aggregate() 方法本身是順序執行的,
它會在所有元素被處理後,順序地合併中間結果。
如果需要在並行環境中安全地合併結果,
並且希望合併操作也是並行的,
那麼可能需要考慮使用 .AsSequential()
來將後續操作轉換為順序執行,
或者使用 .Aggregate() 的執行緒安全版本,
如 .AsParallel().AsOrdered().Aggregate() ,
或者使用鎖來保護共享資源。
using System;
using System.Collections.Generic;
using System.Linq;
class Order
{
public int OrderId { get; set; }
public double TotalAmount { get; set; }
// 假設這是一個非執行緒安全的方法,需要順序呼叫
public void UpdateDatabaseRecord()
{
// 更新資料庫記錄的邏輯
Console.WriteLine($"Order {OrderId} updated in database.");
}
}
class Program
{
static void Main()
{
// 假設這是從資料庫載入的訂單列表
List<Order> orders = Enumerable.Range(1, 1000)
.Select(i => new Order { OrderId = i, TotalAmount = 100.0 * i })
.ToList();
// 使用AsParallel啟動並行查詢
var parallelQuery = orders.AsParallel();
// 並行執行一些操作,比如篩選和投影
var largeOrders = parallelQuery
.Where(o => o.TotalAmount > 500)
.Select(o => new { o.OrderId, o.TotalAmount });
// 在這一點,我們需要順序執行操作,因為UpdateDatabaseRecord是非執行緒安全的
largeOrders.AsSequential().ForEach(order =>
{
order.UpdateDatabaseRecord(); // 順序更新每個訂單的資料庫記錄
});
}
}