0

0

c# ConditionalWeakTable 在并发场景下的应用

幻夢星雲

幻夢星雲

发布时间:2026-01-23 08:27:10

|

405人浏览过

|

来源于php中文网

原创

conditionalweaktable 是线程安全的,但仅限于自身字典操作;其方法内部加锁或使用原子操作,可防止数据结构损坏,适用于 runtimehelpers、wpf 附加属性等底层场景,但回调函数需幂等且避免非线程安全操作。

c# conditionalweaktable 在并发场景下的应用

ConditionalWeakTable 是线程安全的,但不等于“自动解决所有并发问题”

ConditionalWeakTable<tkey tvalue></tkey> 的所有公开方法(AddGetValueTryGetValue 等)内部都加了锁或使用了原子操作,因此**多线程调用不会导致数据结构损坏或崩溃**。这是它被设计用于 RuntimeHelpers.GetOrCreateObjectData、WPF 的附加属性、EF Core 的实体跟踪等底层场景的根本原因。

但要注意:它的线程安全仅限于自身字典操作。如果你在 createValueCallback 里做非线程安全操作(比如修改共享静态变量、访问未同步的集合),依然会出问题。

  • GetValue回调函数可能被多个线程同时触发——即使键相同,只要尚未完成首次创建,多个线程都可能进入回调
  • 回调执行期间,其他线程对同一键的 GetValue 会阻塞等待;但不同键之间完全无干扰
  • 没有内置的“只让第一个线程执行回调,其余等待结果”的去重逻辑——它靠内部锁实现串行化,不是靠 CAS 或 double-check

用 GetValue 创建单例式附加状态时,回调必须幂等

典型场景是给任意对象(比如 Stream 或自定义类实例)附着一个线程本地或生命周期绑定的辅助对象,又不想阻止原对象被回收。这时常配合 GetValue 使用:

var table = new ConditionalWeakTable<MyClass, Lazy<ExpensiveResource>>();
var resource = table.GetValue(obj, _ => new Lazy<ExpensiveResource>(() => new ExpensiveResource()));

上面写法看似简洁,但有隐患:Lazy<expensiveresource></expensiveresource> 的构造本身不执行初始化,而 resource.Value 第一次访问才创建实例——这意味着多个线程仍可能并发进入 new ExpensiveResource(),除非你用 LazyThreadSafetyMode.ExecutionAndPublication(默认就是它)。

  • 更稳妥的做法是直接在回调里返回已构建好的对象,或者确保构造逻辑本身可重入
  • 不要在回调中调用 lock 去保护外部资源——这容易引发死锁,因为 GetValue 内部已有锁
  • 若需延迟初始化 + 线程安全,优先用 Lazy<t></t> 包一层,且显式指定 LazyThreadSafetyMode.ExecutionAndPublication

别把它当 ConcurrentDictionary 用

ConditionalWeakTableConcurrentDictionary 完全不是一回事:

支持手机端的CSS3全屏上下滚动视差特效JS代码
支持手机端的CSS3全屏上下滚动视差特效JS代码

支持手机端的CSS3全屏上下滚动视差特效JS代码,非常不错的JS特效代码,支持手机响应式和PC端,支持鼠标滚轮上下滚动,这种特效代码非常的流行,特别是在微信微场景的使用中,常见这种特效代码,上下滚动加上CSS3动画效果就可以做出用户体验不错的产品介绍页之类的。

下载
  • 前者 key 是弱引用(key 对象被 GC 后,对应条目自动消失),后者是强引用
  • 前者不支持枚举(KeysValuesGetEnumerator 全部抛 NotSupportedException),后者支持
  • 前者没有 Count 属性,无法知道当前挂了多少关联项;后者有
  • 前者不能手动删除(没 Remove 方法),只能等 key 被回收;后者可主动清理

如果你需要“带弱引用语义的并发字典”,ConditionalWeakTable 不满足需求——得自己封装,比如用 ConcurrentDictionary<weakreference>, TValue></weakreference> 并定期清理失效引用,但这会失去 ConditionalWeakTable 的自动清理优势。

调试时看不到内容,别以为没生效

在 Visual Studio 调试器里,ConditionalWeakTable 的字段(如 m_tables)是私有的、内部结构复杂,且调试器不会触发其弱引用遍历逻辑。所以断点停住后展开对象,大概率看到空的 Keys 或报错“not supported”。

验证是否生效,唯一可靠方式是:

  • 写单元测试,用 GC.Collect() + GC.WaitForPendingFinalizers() 后检查原 key 是否还能通过 TryGetValue 拿到值
  • 在回调里打日志,确认是否被调用、调用次数是否符合预期(尤其高并发下)
  • 用内存分析工具(如 dotMemory)查看是否存在意外的强引用链阻止 key 回收

它的行为藏在 GC 和运行时协作深处,表面安静,实际很忙。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
resource是什么文件
resource是什么文件

Resource文件是一种特殊类型的文件,它通常用于存储应用程序或操作系统中的各种资源信息。它们在应用程序开发中起着关键作用,并在跨平台开发和国际化方面提供支持。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

181

2023.12.20

counta和count的区别
counta和count的区别

Count函数用于计算指定范围内数字的个数,而CountA函数用于计算指定范围内非空单元格的个数。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

203

2023.11.20

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

334

2025.08.29

C++中int、float和double的区别
C++中int、float和double的区别

本专题整合了c++中int和double的区别,阅读专题下面的文章了解更多详细内容。

106

2025.10.23

treenode的用法
treenode的用法

​在计算机编程领域,TreeNode是一种常见的数据结构,通常用于构建树形结构。在不同的编程语言中,TreeNode可能有不同的实现方式和用法,通常用于表示树的节点信息。更多关于treenode相关问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

549

2023.12.01

C++ 高效算法与数据结构
C++ 高效算法与数据结构

本专题讲解 C++ 中常用算法与数据结构的实现与优化,涵盖排序算法(快速排序、归并排序)、查找算法、图算法、动态规划、贪心算法等,并结合实际案例分析如何选择最优算法来提高程序效率。通过深入理解数据结构(链表、树、堆、哈希表等),帮助开发者提升 在复杂应用中的算法设计与性能优化能力。

30

2025.12.22

深入理解算法:高效算法与数据结构专题
深入理解算法:高效算法与数据结构专题

本专题专注于算法与数据结构的核心概念,适合想深入理解并提升编程能力的开发者。专题内容包括常见数据结构的实现与应用,如数组、链表、栈、队列、哈希表、树、图等;以及高效的排序算法、搜索算法、动态规划等经典算法。通过详细的讲解与复杂度分析,帮助开发者不仅能熟练运用这些基础知识,还能在实际编程中优化性能,提高代码的执行效率。本专题适合准备面试的开发者,也适合希望提高算法思维的编程爱好者。

44

2026.01.06

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

765

2023.08.10

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

76

2026.03.11

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Django 教程
Django 教程

共28课时 | 4.9万人学习

Excel 教程
Excel 教程

共162课时 | 21.1万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号