.NET?中的線(xiàn)程安全數(shù)據(jù)結(jié)構(gòu)詳解
在多線(xiàn)程編程中,線(xiàn)程安全的數(shù)據(jù)結(jié)構(gòu)是確保數(shù)據(jù)一致性和避免競(jìng)爭(zhēng)條件的關(guān)鍵。.NET 提供了多種線(xiàn)程安全的數(shù)據(jù)結(jié)構(gòu),適用于不同的場(chǎng)景,本篇將介紹它們的簡(jiǎn)單使用以及在 .NET Core 和 .NET Framework 中的可用性。
1. ConcurrentQueue
ConcurrentQueue 是一個(gè)線(xiàn)程安全的先進(jìn)先出 (FIFO) 隊(duì)列。它允許多個(gè)線(xiàn)程同時(shí)進(jìn)行入隊(duì)和出隊(duì)操作,而不會(huì)導(dǎo)致數(shù)據(jù)不一致。
適用場(chǎng)景
- 生產(chǎn)者-消費(fèi)者模式:多個(gè)生產(chǎn)者線(xiàn)程將數(shù)據(jù)項(xiàng)添加到隊(duì)列中,多個(gè)消費(fèi)者線(xiàn)程從隊(duì)列中取出數(shù)據(jù)項(xiàng)進(jìn)行處理
- 任務(wù)調(diào)度:將任務(wù)添加到隊(duì)列中,由工作線(xiàn)程從隊(duì)列中取出任務(wù)并執(zhí)行
優(yōu)點(diǎn)
- 高效的并發(fā)操作:支持多個(gè)線(xiàn)程同時(shí)進(jìn)行入隊(duì)和出隊(duì)操作
- 無(wú)鎖設(shè)計(jì):內(nèi)部使用無(wú)鎖算法,避免了鎖競(jìng)爭(zhēng),提高了性能
- 易于使用:提供簡(jiǎn)單的 API,如
Enqueue
和TryDequeue
可用性
- .NET Framework 4.0 及以上
- .NET Core 1.0 及以上
示例代碼
using System.Collections.Concurrent; var queue = new ConcurrentQueue<int>(); var cts = new CancellationTokenSource(); var token = cts.Token; // 生產(chǎn)者任務(wù) var producer = Task.Run(() => { for (int i = 0; i < 10; i++) { queue.Enqueue(i); Console.WriteLine($"Enqueued {i}"); Thread.Sleep(100); // 模擬生產(chǎn)延遲 } }, token); // 消費(fèi)者任務(wù) var consumer = Task.Run(() => { while (!token.IsCancellationRequested) { if (queue.TryDequeue(out int result)) { Console.WriteLine($"Dequeued {result}"); } Thread.Sleep(50); // 模擬消費(fèi)延遲 } }, token); await Task.WhenAll(producer); cts.Cancel(); // 停止消費(fèi)者任務(wù) await consumer;
2. ConcurrentStack
ConcurrentStack 是一個(gè)線(xiàn)程安全的后進(jìn)先出 (LIFO) 堆棧。它允許多個(gè)線(xiàn)程同時(shí)進(jìn)行入棧和出棧操作。
適用場(chǎng)景
- 深度優(yōu)先搜索算法:在圖或樹(shù)結(jié)構(gòu)中進(jìn)行深度優(yōu)先搜索時(shí)使用
- 撤銷(xiāo)操作:實(shí)現(xiàn)撤銷(xiāo)功能時(shí),將操作記錄入棧,撤銷(xiāo)時(shí)從棧中彈出操作
優(yōu)點(diǎn)
- 高效的并發(fā)操作:支持多個(gè)線(xiàn)程同時(shí)進(jìn)行入棧和出棧操作
- 無(wú)鎖設(shè)計(jì):內(nèi)部使用無(wú)鎖算法,避免了鎖競(jìng)爭(zhēng),提高了性能
- 易于使用:提供簡(jiǎn)單的 API,如
Push
和TryPop
可用性
- .NET Framework 4.0 及以上
- .NET Core 1.0 及以上
示例代碼
using System.Collections.Concurrent; var stack = new ConcurrentStack<int>(); var cts = new CancellationTokenSource(); var token = cts.Token; // 生產(chǎn)者任務(wù) var producer = Task.Run(() => { for (int i = 0; i < 10; i++) { stack.Push(i); Console.WriteLine($"Pushed {i}"); Thread.Sleep(100); // 模擬生產(chǎn)延遲 } }, token); // 消費(fèi)者任務(wù) var consumer = Task.Run(() => { while (!token.IsCancellationRequested) { if (stack.TryPop(out int result)) { Console.WriteLine($"Popped {result}"); } Thread.Sleep(50); // 模擬消費(fèi)延遲 } }, token); await Task.WhenAll(producer); cts.Cancel(); // 停止消費(fèi)者任務(wù) await consumer;
3. ConcurrentBag
ConcurrentBag 是一個(gè)線(xiàn)程安全的無(wú)序集合,適用于頻繁添加和刪除元素的場(chǎng)景。
適用場(chǎng)景
- 任務(wù)池:將任務(wù)添加到集合中,工作線(xiàn)程從集合中取出任務(wù)并執(zhí)行
- 緩存:將臨時(shí)數(shù)據(jù)存儲(chǔ)在集合中,多個(gè)線(xiàn)程可以并發(fā)地添加和刪除數(shù)據(jù)
優(yōu)點(diǎn)
- 高效的并發(fā)操作:支持多個(gè)線(xiàn)程同時(shí)進(jìn)行添加和刪除操作
- 無(wú)鎖設(shè)計(jì):內(nèi)部使用無(wú)鎖算法,避免了鎖競(jìng)爭(zhēng),提高了性能
- 適用于無(wú)序數(shù)據(jù):不關(guān)心元素順序的場(chǎng)景非常適用
可用性
- .NET Framework 4.0 及以上
- .NET Core 1.0 及以上
示例代碼
using System.Collections.Concurrent; var bag = new ConcurrentBag<int>(); var cts = new CancellationTokenSource(); var token = cts.Token; // 生產(chǎn)者任務(wù) var producer = Task.Run(() => { for (int i = 0; i < 10; i++) { bag.Add(i); Console.WriteLine($"Added {i}"); Thread.Sleep(100); // 模擬生產(chǎn)延遲 } }, token); // 消費(fèi)者任務(wù) var consumer = Task.Run(() => { while (!token.IsCancellationRequested) { if (bag.TryTake(out int result)) { Console.WriteLine($"Took {result}"); } Thread.Sleep(50); // 模擬消費(fèi)延遲 } }, token); await Task.WhenAll(producer); cts.Cancel(); // 停止消費(fèi)者任務(wù) await consumer;
4. ConcurrentDictionary<TKey, TValue>
ConcurrentDictionary<TKey, TValue> 是一個(gè)線(xiàn)程安全的鍵值對(duì)集合,類(lèi)似于 Dictionary<TKey, TValue>。
適用場(chǎng)景
- 緩存:存儲(chǔ)鍵值對(duì)數(shù)據(jù),多個(gè)線(xiàn)程可以并發(fā)地讀取和寫(xiě)入緩存
- 計(jì)數(shù)器:存儲(chǔ)計(jì)數(shù)器數(shù)據(jù),多個(gè)線(xiàn)程可以并發(fā)地更新計(jì)數(shù)器值
優(yōu)點(diǎn)
- 高效的并發(fā)操作:支持多個(gè)線(xiàn)程同時(shí)進(jìn)行讀取和寫(xiě)入操作
- 原子操作:支持原子操作,如
AddOrUpdate
和GetOrAdd
,確保數(shù)據(jù)一致性 - 靈活性:提供豐富的 API,支持多種操作
可用性
- .NET Framework 4.0 及以上
- .NET Core 1.0 及以上
示例代碼
using System.Collections.Concurrent; var dictionary = new ConcurrentDictionary<int, string>(); // 添加元素 var addTask = Task.Run(() => { for (int i = 0; i < 10; i++) { dictionary.TryAdd(i, $"value{i}"); Console.WriteLine($"Added key {i} with value value{i}"); } }); // 更新元素 var updateTask = Task.Run(() => { for (int i = 0; i < 10; i++) { var ii = i; dictionary.AddOrUpdate(i, $"new_value{i}", (key, oldValue) => $"new_value{ii}"); Console.WriteLine($"Updated key {i} with value new_value{i}"); } }); // 讀取元素 var readTask = Task.Run(() => { foreach (var key in dictionary.Keys) { if (dictionary.TryGetValue(key, out string? value)) { Console.WriteLine($"Key {key} has value {value}"); } } }); await Task.WhenAll(addTask, updateTask, readTask);
5. BlockingCollection
BlockingCollection 提供線(xiàn)程安全的添加和移除操作,并支持阻塞和限界功能。可以與ConcurrentQueue<T>
, ConcurrentStack<T>
, ConcurrentBag<T>
等一起使用。
適用場(chǎng)景
- 生產(chǎn)者-消費(fèi)者模式:多個(gè)生產(chǎn)者線(xiàn)程將數(shù)據(jù)項(xiàng)添加到集合中,多個(gè)消費(fèi)者線(xiàn)程從集合中取出數(shù)據(jù)項(xiàng)進(jìn)行處理
- 任務(wù)調(diào)度:將任務(wù)添加到集合中,由工作線(xiàn)程從集合中取出任務(wù)并執(zhí)行
優(yōu)點(diǎn)
- 阻塞操作:支持阻塞添加和移除操作,適用于生產(chǎn)者-消費(fèi)者模式
- 限界功能:支持設(shè)置集合的最大容量,防止過(guò)度填充
- 靈活性:可以與多種集合類(lèi)型一起使用,如
ConcurrentQueue<T>
可用性
- .NET Framework 4.0 及以上
- .NET Core 1.0 及以上
示例代碼
using System.Collections.Concurrent; var collection = new BlockingCollection<int>(boundedCapacity: 5); var cts = new CancellationTokenSource(); var token = cts.Token; // 生產(chǎn)者任務(wù) var producer = Task.Run(() => { for (int i = 0; i < 10; i++) { collection.Add(i); Console.WriteLine($"Added {i}"); Thread.Sleep(100); // 模擬生產(chǎn)延遲 } collection.CompleteAdding(); }, token); // 消費(fèi)者任務(wù) var consumer = Task.Run(() => { foreach (var item in collection.GetConsumingEnumerable(token)) { Console.WriteLine($"Consumed {item}"); Thread.Sleep(50); // 模擬消費(fèi)延遲 } }, token); await Task.WhenAll(producer, consumer);
6. ImmutableList
ImmutableList 是線(xiàn)程安全的,因?yàn)樗行薷牟僮鞫紩?huì)返回一個(gè)新的集合實(shí)例。
適用場(chǎng)景
- 配置數(shù)據(jù):存儲(chǔ)配置數(shù)據(jù),多個(gè)線(xiàn)程可以并發(fā)地讀取配置數(shù)據(jù),而無(wú)需擔(dān)心數(shù)據(jù)被修改
- 快照:在某個(gè)時(shí)間點(diǎn)獲取數(shù)據(jù)的快照,多個(gè)線(xiàn)程可以并發(fā)地讀取快照數(shù)據(jù)
優(yōu)點(diǎn)
- 天然線(xiàn)程安全:由于集合不可變,多個(gè)線(xiàn)程可以安全地并發(fā)讀取
- 數(shù)據(jù)一致性:所有修改操作都會(huì)返回一個(gè)新的集合實(shí)例,保證數(shù)據(jù)一致性
- 易于使用:提供豐富的 API,支持多種操作
可用性
- .NET Framework 4.5 及以上(需要安裝
System.Collections.Immutable
NuGet 包) - .NET Core 1.0 及以上(需要安裝
System.Collections.Immutable
NuGet 包)
示例代碼
var list = ImmutableList.Create(1, 2, 3); var newList = list.Add(4); Console.WriteLine(string.Join(", ", newList)); // 輸出 1, 2, 3, 4
7. SynchronizedCollection
SynchronizedCollection 是一個(gè)線(xiàn)程安全的集合,適用于需要同步訪(fǎng)問(wèn)的場(chǎng)景。
適用場(chǎng)景
- 共享資源管理:管理共享資源的集合,多個(gè)線(xiàn)程可以并發(fā)地訪(fǎng)問(wèn)和修改集合
- 事件訂閱:存儲(chǔ)事件訂閱者,多個(gè)線(xiàn)程可以并發(fā)地添加和移除訂閱者
優(yōu)點(diǎn)
- 內(nèi)置同步機(jī)制:自動(dòng)處理同步,確保線(xiàn)程安全
- 易于使用:提供簡(jiǎn)單的 API,如
Add
和Remove
- 靈活性:支持多種集合操作
可用性
- .NET Framework 3.5 及以上
- .NET Core 1.0 及以上
示例代碼
var collection = new SynchronizedCollection<int>(); collection.Add(1); collection.Add(2); foreach (var item in collection) { Console.WriteLine(item); // 輸出 1 和 2 }
8. SynchronizedReadOnlyCollection
SynchronizedReadOnlyCollection 是一個(gè)線(xiàn)程安全的只
讀集合。
適用場(chǎng)景
- 配置數(shù)據(jù):存儲(chǔ)只讀的配置數(shù)據(jù),多個(gè)線(xiàn)程可以并發(fā)地讀取配置數(shù)據(jù)
- 共享數(shù)據(jù):存儲(chǔ)共享數(shù)據(jù),多個(gè)線(xiàn)程可以并發(fā)地讀取數(shù)據(jù),而無(wú)需擔(dān)心數(shù)據(jù)被修改
優(yōu)點(diǎn)
- 內(nèi)置同步機(jī)制:自動(dòng)處理同步,確保線(xiàn)程安全
- 易于使用:提供簡(jiǎn)單的 API,如
Contains
和CopyTo
- 數(shù)據(jù)保護(hù):只讀特性確保數(shù)據(jù)不會(huì)被修改
可用性
- .NET Framework 3.0 及以上
- .NET Core 1.0 及以上
示例代碼
var list = new List<int> { 1, 2, 3 }; var readOnlyCollection = new SynchronizedReadOnlyCollection<int>(list); foreach (var item in readOnlyCollection) { Console.WriteLine(item); // 輸出 1, 2, 3 }
9. SynchronizedKeyedCollection<K, T>
SynchronizedKeyedCollection<K, T> 是一個(gè)線(xiàn)程安全的鍵控集合。
使用場(chǎng)景
- 緩存:存儲(chǔ)鍵控?cái)?shù)據(jù),多個(gè)線(xiàn)程可以并發(fā)地讀取和寫(xiě)入緩存
- 資源管理:管理鍵控資源的集合,多個(gè)線(xiàn)程可以并發(fā)地訪(fǎng)問(wèn)和修改集合
優(yōu)點(diǎn)
- 內(nèi)置同步機(jī)制:自動(dòng)處理同步,確保線(xiàn)程安全
- 鍵控訪(fǎng)問(wèn):支持通過(guò)鍵快速訪(fǎng)問(wèn)元素
- 靈活性:支持多種集合操作
可用性
- .NET Framework 3.0 及以上
- .NET Core 1.0 及以上
示例代碼
public class MyItem { public int Id { get; set; } public string Name { get; set; } } var collection = new SynchronizedKeyedCollection<int, MyItem>(item => item.Id); collection.Add(new MyItem { Id = 1, Name = "Item1" }); collection.Add(new MyItem { Id = 2, Name = "Item2" }); foreach (var item in collection) { Console.WriteLine(item.Name); // 輸出 Item1 和 Item2 }
到此這篇關(guān)于.NET 中的線(xiàn)程安全數(shù)據(jù)結(jié)構(gòu)的文章就介紹到這了,更多相關(guān).NET線(xiàn)程安全數(shù)據(jù)結(jié)構(gòu)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
.net中實(shí)現(xiàn)listBox左右移動(dòng)
這里給大家推薦的是一段網(wǎng)友分享的,使用.net實(shí)現(xiàn)listBox左右移動(dòng)的代碼,簡(jiǎn)單實(shí)用,這里記錄下來(lái),有需要的小伙伴參考下吧。2015-03-03ASP.NET下母版頁(yè)和內(nèi)容頁(yè)中的事件發(fā)生順序整理
母版頁(yè)與內(nèi)容頁(yè)合并后事件的發(fā)生順序,有需要區(qū)別的朋友能用的到2009-03-03.NET Core中HttpClient的正確打開(kāi)方式
這篇文章主要給大家介紹了關(guān)于.NET Core中HttpClient的正確打開(kāi)方式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-01-01asp.net子窗體與父窗體交互實(shí)戰(zhàn)分享
用到了兩個(gè)頁(yè)面,其中Default.aspx作為父頁(yè)面,Default2.aspx作為子頁(yè)面被彈出。Default.aspx頁(yè)面上有兩個(gè)TextBox一個(gè)Button通過(guò)測(cè)試我們可以看出我們保留了先輸入到父窗體中的值,又接收了從子窗體傳遞過(guò)來(lái)的值2013-02-02Asp.Mvc 2.0用戶(hù)服務(wù)器驗(yàn)證實(shí)例講解(4)
這篇文章主要介紹了Asp.Mvc 2.0實(shí)現(xiàn)用戶(hù)服務(wù)器驗(yàn)證功能,需要的朋友可以參考下2015-08-08前臺(tái)JS(jquery ajax)調(diào)用后臺(tái)方法實(shí)現(xiàn)無(wú)刷新級(jí)聯(lián)菜單示例
前臺(tái)用AJAX直接調(diào)用后臺(tái)方法,老有人發(fā)帖提問(wèn),沒(méi)事做個(gè)示例詳細(xì)介紹一下,感興趣的朋友可以參考下2013-01-01