0

0

c# ConditionalWeakTable 和多线程下的对象附加数据

畫卷琴夢

畫卷琴夢

发布时间:2026-01-11 08:06:08

|

106人浏览过

|

来源于php中文网

原创

ConditionalWeakTable 是 .NET 提供的线程安全、弱引用键值映射结构,专为对象附加生命周期绑定数据设计;它通过锁+分段哈希表实现原子操作,避免内存泄漏,适用于为第三方类型动态挂载上下文,但不可替代 ConcurrentDictionary 或用于枚举。

c# conditionalweaktable 和多线程下的对象附加数据

ConditionalWeakTable 是什么,为什么它适合多线程附加数据

ConditionalWeakTable 是 .NET 提供的线程安全、弱引用的键值映射结构,核心用途是为对象“附加”生命周期绑定的数据,且不阻止被附加对象的回收。它内部用锁+分段哈希表实现,所有公开方法(AddGetOrCreateValueTryGetValue)都是线程安全的——这点和 Dictionary 有本质区别:后者即使加了锁,也需手动管理弱引用逻辑,还容易因强引用导致内存泄漏。

典型使用场景包括:为第三方类型(如 Stream 或 ASP.NET Core 的 HttpContext)动态挂载上下文信息,或在 AOP 中注入追踪 ID,而无需修改原类型定义。

多线程下用 GetOrCreateValue 附加数据的正确姿势

必须用 GetOrCreateValue,而不是先 TryGetValueAdd —— 后者存在竞态:两个线程同时发现 key 不存在,都会尝试 Add,触发重复初始化甚至异常(ArgumentException: An item with the same key has already been added)。

  • GetOrCreateValue 内部保证“查找 + 创建”原子性,即使传入的工厂委托被多次调用,也仅有一个结果被最终采纳(其余调用会被丢弃)
  • 工厂委托应是无副作用的纯函数;若初始化逻辑较重(如新建 ConcurrentDictionary),可接受;但避免在里面做 I/O 或锁操作
  • 不要缓存 GetOrCreateValue 返回的值再反复使用——它只是对附加数据的强引用快照,不影响底层弱引用行为
var table = new ConditionalWeakTable>();
var data = table.GetOrCreateValue(someObj, _ => new Dictionary()); // 安全
data["traceId"] = Guid.NewGuid();

常见误用:把 ConditionalWeakTable 当作普通字典用

它不是通用并发字典,不能替代 ConcurrentDictionary

ecshop
ecshop

本版本全面兼容php5.6+,并且修复了许多官方程序的低级代码bug。在apache 2.4.17+php5.6.15环境下测试通过,人格保证无毒无木马,仅仅是一名ecshop热爱者心血来潮之作。ecshop编译更新日志:1、加入最新官方补丁。2、修改数据库连接底层为mysqli, 现在完美无缺了。3、再次对所有代码进行细节修复。4、adminers更新至1.1.2, 在线管理数据库的神器。5、测

下载
  • 不支持枚举(没有 KeysValuesGetEnumerator)——因为键是弱引用,遍历时可能已回收,无法可靠列出全部项
  • 不支持 Remove 方法(.NET 6+ 才有 Remove,且仅用于调试/测试,生产中极少需要主动删)
  • 键类型必须是引用类型,且 table[key] 索引器不存在;只能通过 GetOrCreateValueTryGetValue 访问
  • 如果误用 new ConditionalWeakTable(),运行时不会报错,但字符串常量池中的字面量会被永久驻留,失去弱引用意义

和 ThreadLocal 的关键区别在哪

ThreadLocal 绑定的是“线程”,ConditionalWeakTable 绑定的是“对象实例”。两者解决的问题维度不同:

  • 当你需要“每个请求对象(如 HTTP 请求)带一个独立的上下文”,选 ConditionalWeakTable
  • 当你需要“每个工作线程维持一份本地缓存”,选 ThreadLocal
  • 混合场景(如:为每个请求对象挂一个 ThreadLocal 实例)是可行的,但要注意 ThreadLocal 本身也要被弱引用持有,否则会阻碍线程终结时的清理
  • 注意:.NET 6+ 中 AsyncLocal 更适合异步上下文传播,而 ConditionalWeakTable 仍是最轻量的对象级附着方案

真正容易被忽略的是:ConditionalWeakTable 的线程安全性只覆盖其自身 API,不延伸到你附加的值内部。如果你存了一个非线程安全的 List,多个线程同时操作它依然会出问题——附加数据本身的线程安全要自行保障。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

315

2023.08.02

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1463

2023.10.24

字符串常量的表示方法
字符串常量的表示方法

字符串常量的表示方法:1、使用引号;2、转义字符;3、多行字符串;4、原始字符串;5、字符串连接;6、字符串字面量和对象;7、编码问题。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

139

2023.12.26

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

253

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

206

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1463

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

616

2023.11.24

java读取文件转成字符串的方法
java读取文件转成字符串的方法

Java8引入了新的文件I/O API,使用java.nio.file.Files类读取文件内容更加方便。对于较旧版本的Java,可以使用java.io.FileReader和java.io.BufferedReader来读取文件。在这些方法中,你需要将文件路径替换为你的实际文件路径,并且可能需要处理可能的IOException异常。想了解更多java的相关内容,可以阅读本专题下面的文章。

548

2024.03.22

c++主流开发框架汇总
c++主流开发框架汇总

本专题整合了c++开发框架推荐,阅读专题下面的文章了解更多详细内容。

78

2026.01.09

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
极客学院Java8新特性视频教程
极客学院Java8新特性视频教程

共17课时 | 3.7万人学习

PHP新手语法线上课程教学
PHP新手语法线上课程教学

共13课时 | 0.8万人学习

光速学会docker容器
光速学会docker容器

共33课时 | 1.9万人学习

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

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