`

spring单例在高并发下可能出现的错误

 
阅读更多

spring单例在高并发下可能出现的错误

 

spring单例在高并发下可能出现的错误: 首先,只有当注入的对象是无状态的幂等的才可以保证执行前后不被修改,否则执行一次之后单例对象就会发生改变,在下次执行有肯能造成结果不一样,当在高并发的情况下就会出现,这个线程刚使用单例对象进行属性设置,还未使用的情况下,另一个进程已经将单利对象的数据进行修改属性完成,则远来线程获取到的单例就是一个脏对象不可使用。 当单例对象中含有变化的变量数据,则就不可以使用对象注入的形式注入,那怎么办? 1、在单例对象中进行new对象,这属于线程自己的内存进行存放数据,其他线程无法使用 2、在单例对象中注入了可变对象,则在使用的时候进行copy浅拷贝后使用拷贝后的对象不实用单例对象 3、通过new Callable()轻量级的创建局部变量可以使用上下文变量,属于线程自己的变量 总结:在高并发情况下,单利对象的数据不可以在一个线程使用过,另一个线程调用时单例对象的数据发生改变。 其实单例对象相当于全局变量,线程执行时需要修改数据,再高并发的情况下就会出现当前线程获取到的单例对象数据是脏数据。

 

Spring单例与线程安全小结

一、Spring单例模式与线程安全

 

 
Spring框架里的bean,或者说组件,获取实例的时候都是默认的单例模式,这是在多线程开发的时候要尤其注意的地方。

 

单例模式的意思就是只有一个实例。单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。这个类称为单例类。
当多用户同时请求一个服务时,容器会给每一个请求分配一个线程,这是多个线程会并发执行该请求多对应的业务逻辑(成员方法),此时就要注意了,如果该处理逻辑中有对该单列状态的修改(体现为该单列的成员属性),则必须考虑线程同步问题
同步机制的比较  ThreadLocal和线程同步机制相比有什么优势呢?ThreadLocal和线程同步机制都是为了解决多线程中相同变量的访问冲突问题。 
 
  在同步机制中,通过对象的锁机制保证同一时间只有一个线程访问变量。这时该变量是多个线程共享的,使用同步机制要求程序慎密地分析什么时候对变量进行读写,什么时候需要锁定某个对象,什么时候释放对象锁等繁杂的问题,程序设计和编写难度相对较大。 
 
  而ThreadLocal则从另一个角度来解决多线程的并发访问。ThreadLocal会为每一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。因为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。ThreadLocal提供了线程安全的共享对象,在编写多线程代码时,可以把不安全的变量封装进ThreadLocal。 
 
  由于ThreadLocal中可以持有任何类型的对象,低版本JDK所提供的get()返回的是Object对象,需要强制类型转换。但JDK 5.0通过泛型很好的解决了这个问题,在一定程度地简化ThreadLocal的使用
 概括起来说,对于多线程资源共享的问题,同步机制采用了“以时间换空间”的方式,而ThreadLocal采用了“以空间换时间”的方式。前者仅提供一份变量,让不同的线程排队访问,而后者为每一个线程都提供了一份变量,因此可以同时访问而互不影响。 
 
  Spring使用ThreadLocal解决线程安全问题 
 
  我们知道在一般情况下,只有无状态的Bean才可以在多线程环境下共享,在Spring中,绝大部分Bean都可以声明为singleton作用域。就是因为Spring对一些Bean(如RequestContextHolder、TransactionSynchronizationManager、LocaleContextHolder等)中非线程安全状态采用ThreadLocal进行处理,让它们也成为线程安全的状态,因为有状态的Bean就可以在多线程中共享了。 
 
  一般的Web应用划分为展现层、服务层和持久层三个层次,在不同的层中编写对应的逻辑,下层通过接口向上层开放功能调用。在一般情况下,从接收请求到返回响应所经过的所有程序调用都同属于一个线程
ThreadLocal是解决线程安全问题一个很好的思路,它通过为每个线程提供一个独立的变量副本解决了变量并发访问的冲突问题。在很多情况下,ThreadLocal比直接使用synchronized同步机制解决线程安全问题更简单,更方便,且结果程序拥有更高的并发性。 
如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。 或者说:一个类或者程序所提供的接口对于线程来说是原子操作或者多个线程之间的切换不会导致该接口的执行结果存在二义性,也就是说我们不用考虑同步的问题。  线程安全问题都是由全局变量及静态变量引起的。  
若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则就可能影响线程安全。
1) 常量始终是线程安全的,因为只存在读操作。 
2)每次调用方法前都新建一个实例是线程安全的,因为不会访问共享的资源。
3)局部变量是线程安全的。因为每执行一个方法,都会在独立的空间创建局部变量,它不是共享的资源。局部变量包括方法的参数变量和方法内变量。
有状态就是有数据存储功能。有状态对象(Stateful Bean),就是有实例变量的对象  ,可以保存数据,是非线程安全的。在不同方法调用间不保留任何状态。
无状态就是一次操作,不能保存数据。无状态对象(Stateless Bean),就是没有实例变量的对象  .不能保存数据,是不变类,是线程安全的。
有状态对象:
无状态的Bean适合用不变模式,技术就是单例模式,这样可以共享实例,提高性能。有状态的Bean,多线程环境下不安全,那么适合用Prototype原型模式。Prototype: 每次对bean的请求都会创建一个新的bean实例。
Struts2默认的实现是Prototype模式。也就是每个请求都新生成一个Action实例,所以不存在线程安全问题。需要注意的是,如果由Spring管理action的生命周期, scope要配成prototype作用域

 

分享到:
评论

相关推荐

    spring 业务层架构

    因此,业务层的设计不仅要考虑功能性,还要考虑到性能优化,确保能够在高并发环境下稳定运行。 #### 二、业务层架构原则 1. **模块化原则**:模块化是软件开发中的一种基本策略,其目的是为了降低系统的复杂度,...

    java面试Spring.pdf

    2. **依赖反射**:Spring大量使用反射技术,虽然带来了灵活性,但也可能影响性能,尤其是在高并发场景下。 3. **学习成本**:掌握Spring的所有特性和最佳实践需要一定的时间投入。 **核心容器(Spring Context应用...

    Spring整合JMS.doc

    然而,在高并发、高可用性等场景下,还需要考虑消息的持久化、重试策略以及错误处理机制,以确保消息的可靠传递和处理。 综上所述,Spring整合JMS与ActiveMQ是一项涉及多个层面的技术实践,从理论基础到具体实现,...

    spring+springMVC全量jar包

    2. **反应式编程**:Spring 5 引入了Reactor,支持非阻塞I/O和反应式流API,适应了微服务和高并发场景。 3. **WebSocket 支持**:提供了更好的WebSocket支持,使得实时通信更加方便。 4. **更好的错误处理**:改进了...

    ssh 问题整理

    然而,当使用Spring进行依赖注入时,如果注入的对象不是线程安全的,比如单例模式下非静态的成员变量,那么在多线程环境下可能会出现并发问题,导致数据不一致。在这种情况下,将需要注入的类声明为`static`,或者...

    第大数据微服务架构+区块链第8单元 练习手册试题及答案.pdf

    6. 在并发编程中,`ConcurrentHashMap` 是一种线程安全且高效的数据结构,适合高并发场景下对 Key-Value 存储的需求。 7. Collections 是 Java 提供的集合操作工具类,提供了很多静态方法来操作集合。泛型引入后,...

    java 反模式 卷3 pdf

    例如,书中可能讨论了过度使用单例模式导致的灵活性缺失,或者在并发处理中不恰当的锁机制,这些都可能导致系统出现难以调试的问题。 J2EE反模式部分则专门关注企业级Java应用开发中的陷阱。J2EE平台提供了丰富的...

    商业编程-源码-稻草图书管理系统.zip

    性能测试和压力测试则可能通过JMeter或LoadRunner进行,保证系统在高并发情况下也能稳定运行。 总的来说,《稻草图书管理系统》的源码揭示了商业编程中的诸多关键技术和最佳实践,包括但不限于软件架构设计、数据库...

    java源码:车间管控.rar

    2. **多线程**:在车间管控系统中,可能会用到多线程技术来处理并发操作,如设备的异步操作、数据的实时更新等。Java提供了Thread类和Runnable接口来支持多线程编程,同时,高级的并发工具如ExecutorService和Future...

    高级面试题

    8. CAP理论中的CP指的是在分布式系统中,Consistency(一致性)和Availability(可用性)的取舍,若要在高并发、实时性要求不高的场景下抉择,通常会优先保证数据一致性。 9. 分布式事务是在分布式系统中跨越多个...

    HslCommunication的Java版本的项目.zip

    通过参与这样的实战项目,开发者可以提升对Java网络编程的理解,掌握高并发环境下通信框架的设计和实现,为构建大规模分布式系统打下坚实基础。同时,这也是一次学习如何将理论知识转化为实际应用的宝贵机会。

    互联网高频Java后端面试题20道(适合1~3年)V1.0.44.docx

    这提供了程序的健壮性,确保即使在出现错误时也能优雅地处理和恢复。解析:异常处理是程序错误处理的关键,try-catch-finally 结构使得开发者能够分离正常逻辑和异常处理逻辑,提高代码的可读性和错误处理能力。 ...

    明日知道java源码.zip

    8. **消息队列**:如果涉及异步处理,可能使用RabbitMQ或Kafka来处理高并发场景下的消息传递。 此外,Java的框架如Spring Boot和Spring Cloud可以简化开发流程,提供自动化配置和微服务架构支持。这些框架可以帮助...

    java 商品订单的资源

    4. **并发控制**:在高并发环境下,订单系统需要处理多个用户同时提交订单的情况。Java提供了synchronized关键字和Lock接口来保证线程安全,防止数据竞争。 5. **设计模式**:在商品订单系统中,常见的设计模式有...

    Java工作学习牛客网刷题错误总结.rar

    这份“Java工作学习牛客网刷题错误总结”压缩包文件,显然是作者在解决这些题目时遇到的问题和错误的汇总,对于其他Java学习者来说具有很高的参考价值。本文将详细解析其中可能包含的知识点,并进行深入探讨。 1. *...

    java笔试题,面试题

    例如,可能会遇到空指针异常、数组越界、类型转换异常等问题,或者是算法实现上的错误,如排序算法的逻辑错误,或者在多线程环境下未正确处理同步导致的竞态条件。 “笔试题.txt”可能包含了更多理论和实践相结合的...

    Java高级程序设计实战教程-源代码.rar

    7. **泛型**:泛型提供了一种在编译时类型安全的方式来处理集合,避免了类型转换的麻烦,并减少了运行时错误的可能性。 8. **JVM优化**:理解JVM的工作原理,如垃圾收集、内存模型、类加载机制等,可以帮助优化代码...

    JAVA案例开发集锦!!!

    数据库连接与操作也是常见的需求,因此JDBC(Java Database Connectivity)的使用,包括数据库连接、执行SQL语句、处理结果集等,也可能在案例中出现。 Java还提供了丰富的API,如Swing或JavaFX用于桌面应用开发,...

    JAVA SMART系统-系统框架设计与开发(1).zip

    Spring的IoC容器管理对象的生命周期,而AOP则允许我们在不修改代码的情况下添加额外的功能。 2. **MVC模式**:在系统框架设计中,模型-视图-控制器(MVC)架构模式是常见的设计模式。Java中的Struts和Spring MVC都是...

    java代码集锦

    try-catch-finally语句块用于捕获并处理可能出现的错误,保证程序的正常运行。 4. **集合框架**:Java集合框架包括ArrayList、LinkedList、HashSet、HashMap等数据结构,用于存储和操作数据。代码示例可能会展示...

Global site tag (gtag.js) - Google Analytics