ภาพรวม
Namespace System.Collections.Concurrent (เพิ่มใน .NET Framework 4) จัดเตรียมคอลเลกชันที่ปลอดภัยต่อเธรด (thread-safe) และ scalable สำหรับการเข้าถึงพร้อมกันจากหลายเธรด
คอลเลกชันหลักใน Namespace นี้
| คลาส | คำอธิบาย | เหมาะสำหรับ |
|---|---|---|
BlockingCollection<T> | คอลเลกชันที่รองรับการ block เมื่อเต็มหรือว่าง | Producer-Consumer patterns |
ConcurrentDictionary<TKey,TValue> | Dictionary ที่ thread-safe | Cache, shared state |
ConcurrentQueue<T> | Queue แบบ FIFO ที่ thread-safe | Task queues, message passing |
ConcurrentStack<T> | Stack แบบ LIFO ที่ thread-safe | Object pooling, undo operations |
ConcurrentBag<T> | คอลเลกชันไม่มีลำดับ Thread-safe | Thread-local storage aggregation |
IProducerConsumerCollection<T> | Interface สำหรับ custom collections ใช้กับ BlockingCollection | Custom concurrent collections |
ตัวอย่าง: ConcurrentDictionary
using System;
using System.Collections.Concurrent;
using System.Threading.Tasks;
public class Demo {
static ConcurrentDictionary<string, int> counts = new ConcurrentDictionary<string, int>();
public static void Main() {
Parallel.For(0, 1000, i => {
string key = $"Key{i % 10}";
counts.AddOrUpdate(key, 1, (k, v) => v + 1);
});
foreach (var kvp in counts) {
Console.WriteLine($"{kvp.Key}: {kvp.Value}");
}
}
}
ตัวอย่าง: BlockingCollection (Producer-Consumer)
var queue = new BlockingCollection<int>(boundedCapacity: 100);
// Producer
Task.Run(() => {
for (int i = 0; i < 10; i++) {
queue.Add(i);
Thread.Sleep(100);
}
queue.CompleteAdding();
});
// Consumer
Task.Run(() => {
foreach (var item in queue.GetConsumingEnumerable()) {
Console.WriteLine($"Consumed: {item}");
}
});
หมายเหตุ
- ใช้ SpinLock, SpinWait สำหรับ synchronization แบบ輕量 (lightweight)
- ไม่ต้องใช้
lockเอง คอลเลกชันจัดการเองแล้ว - เหมาะสำหรับ high-contention scenarios
ConcurrentBagไม่รักษาลำดับ เหมาะสำหรับเก็บข้อมูลชั่วคราวจากหลายเธรด