登录
/
注册
首页
论坛
其它
首页
科技
业界
安全
程序
广播
Follow
园子
关于
博客
发1篇日志+1圆
记录
发1条记录+2圆币
发帖说明
登录
/
注册
账号
自动登录
找回密码
密码
登录
立即注册
搜索
搜索
关闭
CSDN热搜
程序园
精品问答
技术交流
资源下载
本版
帖子
用户
软件
问答
教程
代码
VIP申请
网盘
联系我们
道具
勋章
任务
设置
我的收藏
退出
腾讯QQ
微信登录
返回列表
首页
›
业界区
›
业界
›
从配置读取到懒加载模式:从具体问题到抽象设计语素的提 ...
从配置读取到懒加载模式:从具体问题到抽象设计语素的提炼
[ 复制链接 ]
福清婉
4 天前
在实际项目中,我们常常需要高效、线程安全地加载配置文件。为了确保在高并发场景下配置只加载一次、且读取速度尽可能快,我们往往会设计一些特殊的加载方案。今天,我将记录一次从具体实现问题出发,逐步抽象出高级设计概念的过程。
1. 高效加载配置的需求
在项目初期,我们的需求很简单:
如何在多线程环境下高效加载配置
。为了避免重复加载和可能的线程竞争,我们通常会先检查配置是否已经加载。如果已加载,则直接返回;如果没有,则进入初始化阶段。这样既保证了性能,又保证了加载的唯一性。
例如,一个常见的实现思路如下:
if (_config != null)
return _config;
lock (_lock)
{
if (_initialized)
return _config ?? throw new InvalidOperationException($"加载配置失败{_path}");
_initialized = true;
//初始化操作。
_config = LoadConfig();
}
复制代码
这段代码试图通过锁外的判空和锁内的 _initialized 标志来保证加载逻辑的线程安全和高效。
2. 关于 ?? throw 的讨论
在初始化代码中,我们看到了一行:
return _config ?? throw new InvalidOperationException($"加载配置失败{_path}");
复制代码
这行代码的作用是在 _config 为 null 时,立即抛出异常,提示加载配置失败。那么问题来了:
在这里是否有必要进行 _config 的空判断?
从设计上讲,如果初始化成功,那么 _config 应该始终不为空。但 LoadConfig(); 可能抛出异常,为了防御不可预期的情况,开发者可能会添加这种额外的检查。这种做法在一定程度上可以捕获那些可能出现的意外情况,但同时也反映出状态管理上可能存在的不一致问题。
如果初始化失败,_initialized 不应该被置为 true。也就是说,只有在 _config 确保被正确赋值后,再设置 _initialized 为 true。这样可以确保状态的一致性,从而避免在后续调用时出现 _initialized 为 true 而 _config 为 null 的情况。改进一下代码:
if (_config != null)
return _config;
lock (_lock)
{
if (_initialized)
return _config;//无需再判断_config是否为空
//初始化操作。
_config = LoadConfig();
_initialized = true;//将这行放在_config赋值之后
}
复制代码
这样就能解决问题了。
3. _initialized 变量的冗余性
进一步分析后,我们会发现: _initialized 变量显得多余了。只需要依靠 _config 的非空判断就可以判断配置是否已加载。
代码可以重构为更简单的形式,只关注 _config 的状态,从而实现更直观和可靠的逻辑。
if (_config != null)
return _config;
lock (_lock)
{
if (_config != null)
return _config;
//初始化操作。
_config = LoadConfig();
}
复制代码
4. 经典的双重判空检查
仔细回顾,我们的这种实现实际上就是经典的
双重判空检查
模式。最外层的 _config 判空用于提高效率(避免不必要的锁),而在锁内部再进行一次检查确保线程安全。这是解决懒加载问题的一种传统方法。
5. 编程语言内置封装
针对上述问题,C# 提供了内置的懒加载机制——
Lazy
,避免手动管理锁和状态标记。
6. 从具体实例到抽象设计语素的提炼
回顾整个过程,从最初为了解决配置加载的性能和线程安全问题,到思考状态同步与是否需要额外的 _initialized 标记,到识别这是经典的双重判空检查,我们实际上经历了一次从具体实例到抽象设计语素的提炼过程。
这种思考模式与科学研究中从具体实验现象提炼出普适规律非常相似。通过对问题的不断深入理解和抽象,我们可以形成一套更为通用的设计原则,这些原则可以在日后的其他场景中反复使用,成为开发者手中的基本设计语素。
这种从具体案例中总结经验,并提炼出抽象设计理念的方法,不仅提升了代码质量,还极大地提高了系统的可维护性和扩展性。正是这种持续迭代和抽象提升的过程,推动了软件设计模式和工程实践的发展。
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复
使用道具
举报
提升卡
置顶卡
沉默卡
喧嚣卡
变色卡
千斤顶
照妖镜
相关推荐
那些年搞不懂的高深术语——依赖倒置•控制反转•依赖注入•面向接口编程
如何优雅的使用RabbitMQ
分布式锁1 Java常用技术方案
浅谈我对DDD领域驱动设计的理解
游戏编程十年总结(下)
【前端性能】高性能滚动 scroll 及页面渲染优化
验证码对抗之路及现有验证机制介绍
从零开始入门 K8s | 手把手带你理解 etcd
中文写程序,何陋之有?
NHibernate之旅(2):第一个NHibernate程序
公司的中场
谈谈如何从本质上理解sql语句, 存储过程,ORM之间的联系和取舍。
Android 系统缺陷不完全点评
FFmpeg开发笔记(六十二)Windows给FFmpeg集成H.266编码器vvenc
[一步一步MVC]第一回:使用ActionSelector控制Action的选择
.net环境下跨进程、高频率读写数据
第二个iPhone应用程序:“Say Hello”
从零开始学习jQuery (十一) 实战表单验证与自动完成提示插件
高级模式
B
Color
Image
Link
Quote
Code
Smilies
您需要登录后才可以回帖
登录
|
立即注册
回复
本版积分规则
回帖并转播
回帖后跳转到最后一页
签约作者
程序园优秀签约作者
发帖
福清婉
4 天前
关注
0
粉丝关注
6
主题发布
板块介绍填写区域,请于后台编辑
财富榜{圆}
敖可
9988
森萌黠
9996
堵赫然
9996
4
凶契帽
9996
5
处匈跑
9996
6
柴古香
9996
7
背竽
9996
8
斜素欣
9994
9
恐肩
9994
10
里豳朝
9994
查看更多