关于单例模式的心结

简介: 今天重构公司的代码,看到有一个单例的对象,在整个系统中到处都存在调用它的身影,因为我们这个项目会在应用服务器(server)第一次启动的时候加载数据库中的代码表(为什么要先加载,因为这个项目采用的是C/S模式,利用remoting进行通信,在客户端启动的时候会多次获取代码表中的不同数据。

  今天重构公司的代码,看到有一个单例的对象,在整个系统中到处都存在调用它的身影,因为我们这个项目会在应用服务器(server)第一次启动的时候加载数据库中的代码表(为什么要先加载,因为这个项目采用的是C/S模式,利用remoting进行通信,在客户端启动的时候会多次获取代码表中的不同数据。)

 1  public class CodeTableSingleTon
 2 {
 3     ///防止外部被实例化
 4    private CodeTableSingleTon(){
 5        //进行数据的读取操作
 6    }
 7    //
 8   private static readonly object _lock=new object();
 9 
10   private static CodeTableSingleTon _instance;
11   
12    public static CodeTableSingleTon Instance
13   {
14   get
15    {
16     if(_instance==null)
17      {
18          lock(_lock){
19             if(_instance==null) 
20             {
21             _instance=new CodeTableSingleTon();   
22             }
23           }
24     }
25   return _instance;
26    }
27 }
28 
29 
30 }

上面代码就是项目的实现方式,我了解过单例模式,单例模式是控制对象的创建,可以实现延迟加载,只有在对象被调用的时候才会真正的执行对象的实例化,可以在一定程度上减少内存的耗用(是在不使用该对象的情况下)。既然在整个系统中只有一个该对象, 因为项目是采用多线程处理客户端的请求,所以每个线程都可以获取到该对象进行数据的获取,系统运行也没发现 由于这个对象的创建或者其他问题。

 

  但是我深入的想了一下,如果我在单例对象中加入一个计数器,表示单例对象被调用的次数,那么这个对象内部的属性 可能会同时被多个线程进行更新。

 1 public class SingleTon
 2 {
 3 
 4   private static SingleTon _instance;
 5   private static readonly object _lock=new object();
 6   private SingleTon(){} //私有的构造函数 确保该实例不能在外部直接通过new实例化
 7   public static long totalNum=0;//初始化计数器默认值为0
 8   public static SingleTon Instance
 9   {
10   get  
11   {
12     if(_instance==null)
13       {
14        lock(_lock)
15        {
16           if(_instance==null)
17           {
18           _instance=new SingleTon();
19           }
20        }
21       }
22       totalNum=totalNum+1; //每次调用计数器都会加1
//Consle.WriteLine(totalNum);
23 return _instance; 24 } 25 } 26 }

 

我尝试开启了多个线程来执行这段代码,没有发现totalNum的值存在由于多个线程的调用出现重复数据输出的情况。那么我心里一直在纠结一个事,就是说假如两个线程都在同一时间获取到了这个单例对象,那么都会依次执行计数器加1,如果说两个线程执行到totalNum=totalNum+1 这句话的时候不是在同时的,那么不会出现问题。

如果这两个线程中了彩票了,同时执行了totalNum=totalNum+1,那么就会导致计数器少算了一次调用吗?我在测试,开启了100个线程,没有发现重复的值存在,难道我的理解是错误的吗?我记得在多线程下操作同一数据是会出现这个问题的?不知道这个对单例模式是否适用呢?纠结纠结,求准确的回复

 

如果单例的方式存在问题,那么采用静态字段也会出现这个问题,就无法统计计数器了。mygod  脑袋要炸了

 

我又回来了,回到了技术最前线,
相关文章
|
Java 开发者 Python
Python中的self是什么你知道嘛?
在Python类中规定,函数的第一个参数是实例对象本身,并且约定俗成,把其名字写为self。其作用相当于java中的this,表示当前类的对象,可以调用当前类中的属性和方法。
|
8月前
|
存储 消息中间件 druid
Druid 架构原理及核心特性详解
Druid 是一个分布式、支持实时多维OLAP分析的列式存储数据处理系统,适用于高速实时数据读取和灵活的多维数据分析。它通过Segment、Datasource等元数据概念管理数据,并依赖Zookeeper、Hadoop和Kafka等组件实现高可用性和扩展性。Druid采用列式存储、并行计算和预计算等技术优化查询性能,支持离线和实时数据分析。尽管其存储成本较高且查询语言功能有限,但在大数据实时分析领域表现出色。
1639 19
|
JSON 安全 API
如何高效编写API接口:以Python与Flask为例
构建RESTful API的简明教程:使用Python的Flask框架,从环境准备(安装Python,设置虚拟环境,安装Flask)到编写首个API(包括获取用户列表和单个用户信息的路由)。运行API服务器并测试在`http://127.0.0.1:5000/users`。进阶话题包括安全、数据库集成、API文档生成和性能优化。【6月更文挑战第27天】
343 7
|
XML 前端开发 JavaScript
Vue vs. React:比较两大前端框架的特点与区别
Vue.js和React.js是目前前端开发中最受欢迎的两个JavaScript框架之一。虽然它们都用于构建现代、响应式的用户界面,但在细节和设计理念上存在一些重要的区别。在本博客中,我们将深入研究Vue和React之间的不同之处,以帮助您选择适合您项目需求的框架。
1850 0
|
JSON 缓存 JavaScript
node.js(2)
简介 什么是模板化 将一个复杂的程序文件依据一定规则(规范)拆分成多个文件的过程称之为 模块化 好处 下面是模块化的一些好处: 防止命名冲突 高复用性 高维护性 暴露数据 如何暴露两种方式
103 0
|
编译器 C语言 C++
c++初阶------类和对象(六大默认构造函数的揭破)-3
c++初阶------类和对象(六大默认构造函数的揭破)
|
移动开发 小程序 JavaScript
uView Slider 滑动选择器
uView Slider 滑动选择器
235 0
|
存储 SQL 算法
LeetCode题目43:字符串相乘
LeetCode题目43:字符串相乘
|
存储 前端开发 搜索推荐
前端开发中值得关注的三个Web API
【2月更文挑战第4天】Web API是前端开发中非常重要的一部分,它们为开发者提供了众多的功能和特性,帮助我们构建更加高效、优美的Web应用。本文将介绍三个值得关注的Web API,包括Web Storage、Geolocation和Web Notifications,希望能够对前端开发者有所帮助。
|
移动开发 安全 Shell
如何排查网站及APP数据遭到泄露的问题
近年来数据泄露安全事件频发,在今年的hw网络安全攻防演练中,获取敏感信息、数据泄露等漏洞的得分也越来越高,我们SINE安全近十年来成功的帮助了许多客户,查找到了数据泄露的原因,在这里向大家分享我们的经验与心得,包括数据泄露的排查办法以及修复。
315 0