首页 > 其他分享 >.NET 中的线程安全数据结构

.NET 中的线程安全数据结构

时间:2024-12-25 11:08:55浏览次数:3  
标签:场景 Task 线程 var new NET 数据结构

目录
在多线程编程中,线程安全的数据结构是确保数据一致性和避免竞争条件的关键。.NET 提供了多种线程安全的数据结构,适用于不同的场景,本篇将介绍它们的简单使用以及在 .NET Core 和 .NET Framework 中的可用性。

1. ConcurrentQueue

ConcurrentQueue 是一个线程安全的先进先出 (FIFO) 队列。它允许多个线程同时进行入队和出队操作,而不会导致数据不一致。

使用场景

  • 适用于生产者-消费者模式
  • 需要保证元素按添加顺序处理的场景

优点

  • 高效的并发操作
  • 无需显式锁定

可用性

  • .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;

// 生产者任务
var producer = Task.Run(() =>
{
    for (int i = 0; i < 10; i++)
    {
        queue.Enqueue(i);
        Console.WriteLine($"Enqueued {i}");
        Thread.Sleep(100); // 模拟生产延迟
    }
}, token);

// 消费者任务
var consumer = Task.Run(() =>
{
    while (!token.IsCancellationRequested)
    {
        if (queue.TryDequeue(out int result))
        {
            Console.WriteLine($"Dequeued {result}");
        }
        Thread.Sleep(50); // 模拟消费延迟
    }
}, token);

await Task.WhenAll(producer);
cts.Cancel(); // 停止消费者任务
await consumer;

2. ConcurrentStack

ConcurrentStack 是一个线程安全的后进先出 (LIFO) 堆栈。它允许多个线程同时进行入栈和出栈操作。

使用场景

  • 适用于需要后进先出处理的场景
  • 适用于深度优先搜索算法

优点

  • 高效的并发操作
  • 无需显式锁定

可用性

  • .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;

// 生产者任务
var producer = Task.Run(() =>
{
    for (int i = 0; i < 10; i++)
    {
        stack.Push(i);
        Console.WriteLine($"Pushed {i}");
        Thread.Sleep(100); // 模拟生产延迟
    }
}, token);

// 消费者任务
var consumer = Task.Run(() =>
{
    while (!token.IsCancellationRequested)
    {
        if (stack.TryPop(out int result))
        {
            Console.WriteLine($"Popped {result}");
        }
        Thread.Sleep(50); // 模拟消费延迟
    }
}, token);

await Task.WhenAll(producer);
cts.Cancel(); // 停止消费者任务
await consumer;

3. ConcurrentBag

ConcurrentBag 是一个线程安全的无序集合,适用于频繁添加和删除元素的场景。

使用场景

  • 适用于需要频繁添加和删除元素的场景
  • 适用于不关心元素顺序的场景

优点

  • 高效的并发操作
  • 无需显式锁定

可用性

  • .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;

// 生产者任务
var producer = Task.Run(() =>
{
    for (int i = 0; i < 10; i++)
    {
        bag.Add(i);
        Console.WriteLine($"Added {i}");
        Thread.Sleep(100); // 模拟生产延迟
    }
}, token);

// 消费者任务
var consumer = Task.Run(() =>
{
    while (!token.IsCancellationRequested)
    {
        if (bag.TryTake(out int result))
        {
            Console.WriteLine($"Took {result}");
        }
        Thread.Sleep(50); // 模拟消费延迟
    }
}, token);

await Task.WhenAll(producer);
cts.Cancel(); // 停止消费者任务
await consumer;

4. ConcurrentDictionary<TKey, TValue>

ConcurrentDictionary<TKey, TValue> 是一个线程安全的键值对集合,类似于 Dictionary<TKey, TValue>。

使用场景

  • 适用于需要频繁读取和写入键值对的场景
  • 适用于需要线程安全的字典操作的场景

优点

  • 高效的并发操作
  • 支持原子操作,如AddOrUpdate和GetOrAdd`

可用性

  • .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 提供线程安全的添加和移除操作,并支持阻塞和限界功能。可以与ConcurrentQueue<T>, ConcurrentStack<T>, ConcurrentBag<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;

// 生产者任务
var producer = Task.Run(() =>
{
    for (int i = 0; i < 10; i++)
    {
        collection.Add(i);
        Console.WriteLine($"Added {i}");
        Thread.Sleep(100); // 模拟生产延迟
    }
    collection.CompleteAdding();
}, token);

// 消费者任务
var consumer = Task.Run(() =>
{
    foreach (var item in collection.GetConsumingEnumerable(token))
    {
        Console.WriteLine($"Consumed {item}");
        Thread.Sleep(50); // 模拟消费延迟
    }
}, token);

await Task.WhenAll(producer, consumer);

6. ImmutableList

ImmutableList 是线程安全的,因为所有修改操作都会返回一个新的集合实例。

使用场景

  • 适用于需要线程安全且不希望集合被修改的场景
  • 适用于需要快照功能的场景

优点

  • 天然线程安全
  • 不可变性保证数据一致性

可用性

  • .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 是一个线程安全的集合,适用于需要同步访问的场景。

使用场景

  • 适用于需要同步访问集合的场景
  • 适用于需要线程安全的集合操作的场景

优点

  • 内置同步机制
  • 线程安全的集合操作

可用性

  • .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 是一个线程安全的只
读集合。

使用场景

  • 适用于需要线程安全的只读集合的场景
  • 适用于需要同步访问集合的场景

优点

  • 内置同步机制
  • 线程安全的只读集合操作

可用性

  • .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> 是一个线程安全的键控集合。

使用场景

  • 适用于需要线程安全的键控集合的场景
  • 适用于需要同步访问集合的场景

优点

  • 内置同步机制
  • 线程安全的键控集合操作

可用性

  • .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
}

标签:场景,Task,线程,var,new,NET,数据结构
From: https://www.cnblogs.com/Tangtang1997/p/18629960

相关文章

  • Kubernetes应用编排控制器
    1.Kubernetes控制器模式1.1声明式APIAPI设计方法命令式API也称为指令式API,用户需要一步步地告诉机器该如何做(How),机器自身不具有任何“智能”,只被动接受指令高度依赖用户自身理解和达成目标的能力和处理各类异常问题的经验,实现的是“命令式编程(ImperativeProgramming)”......
  • DotNetCore 3.1桌面应用在Windows 7 SP1 X86下不能运行的问题的解决方法
    遇到的问题一个小的桌面应用,发布到Windows7SP1x86系统,打包成Self-Contained进行发布的时候,运行后没反应,也不报错。打包成SingleFile之后,运行报错api-ms-win-crt-runtime-l1-1-0.dll缺失。之后尝试安装.NetCore3.1的DesktopRuntime,问题依旧。然后又搜索一阵,大概是Windows......
  • 线程池前世今生及源码实现
    @目录⭐前序一、是什么(what)@功能构成二、为什么(why)三、何处(where)四、何时(when)五、谁(who)六、怎么样(how)@实践和性能调优策略@线程池源码(Code)[待补充]⭐前序本文讲什么:线程池的概念、工作原理、优势、实际应用中的使用场景和注意事项,以及一些最佳实践和性能调优策略......
  • 4、数据结构与算法解析(C语言版)--栈
    栈的数据存储遵循“后进先出的规则”,这在计算机里面是非常有用的,比如word等编辑软件的"撤销"功能,就是使用栈进行实现的。1、创建项目 main.h#ifndef_MAIN_H#define_MAIN_H#include<stdio.h>#include<stdlib.h>#include<time.h>#defineTRUE1#defineFALSE0......
  • .NET周刊【12月第3期 2024-12-15】
    国内文章重磅推出SdcbChats:一个全新的开源大语言模型前端https://www.cnblogs.com/sdcb/p/18597030/sdcb-chats-introSdcbChats是一个新推出的开源大语言模型前端,旨在提升用户交互体验,并填补市场上基于.NET的前端空白。它引入树状消息结构,允许用户方便地与模型互动并优化对......
  • C#/.NET/.NET Core技术前沿周刊 | 第 18 期(2024年12.16-12.22)
    前言C#/.NET/.NETCore技术前沿周刊,你的每周技术指南针!记录、追踪C#/.NET/.NETCore领域、生态的每周最新、最实用、最有价值的技术文章、社区动态、优质项目和学习资源等。让你时刻站在技术前沿,助力技术成长与视野拓宽。欢迎投稿、推荐或自荐优质文章、项目、学习资源等。......
  • golang中线程安全的map
    golang中线程安全的两种数据结构:channelsync.Map保证线程安全可以使用sync包下面的互斥锁sync.Mutex读写锁sync.RWMutex原子操作sync.atomicmap的底层原理count:key的数量flags:是否进行写操作B:桶的数量,它是以2为底的对数,即2的B次方hash0:哈希因子buckets:桶的列表,一个bma......
  • 省选集训 day 1 数据结构杂题
    A比较套路的题目,第一次见还是有难度的。关于\(+1\)的更改,事实上是找到二进制下极长的末尾\(1\)段并进位。考虑使用Trie维护这个操作,相当于建立一颗从低位开始的Trie,然后swap儿子并进入swap后的新左子树递归操作。然后对于邻域的问题,一般考虑每个点单独维护其儿子,然后特......
  • Kubernetes 的架构和核心概念
    Kurbernetes是Google旗下的容器跨主机编排工具。Kurbernetes可以自动化应用容器的部署、扩展和操作,提供以容器为中心的基础架构。一、Kurbernetes集群架构与组件Kubernetes采用主从分布式架构,节点在角色上分为Maste和Node。KubernetesMaster是控制节......
  • Deep Learning Convolutional Neural Networks
    LapProject–DeepLearningObjectiveThisexperimentaimstohelpstudentsunderstandConvolutionalNeuralNetworks(CNNs)andtheirapplicationsindeeplearningbyimplementinganimagerecognitionmodel.StudentswillusetheCombinedCOCOdataset,do......