精华内容
下载资源
问答
  • spring 中的 bean线程安全的吗?

    万次阅读 2019-07-16 14:55:53
    spring 中的 bean线程安全的吗? Spring 不保证 bean线程安全。 默认 spring 容器中的 bean 是单例的。当单例中存在竞态条件,即有线程安全问题。如下面的例子 计数 package constxiong.interview....

    spring 中的 bean 是线程安全的吗?

     Spring 不保证 bean 的线程安全。
    默认 spring 容器中的 bean 是单例的。当单例中存在竞态条件,即有线程安全问题。如下面的例子

    计数类

    package constxiong.interview.threadsafe;
    
    /**
     * 计数类
     * @author ConstXiong
     * @date 2019-07-16 14:35:40
     */
    public class Counter {
    
    	private int count = 0;
    	
    	public void addAndPrint() {
    		try {
    			Thread.sleep(10);
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    		System.out.println(++count);
    	}
    	
    }
    

     

    spring 配置文件

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xmlns:context="http://www.springframework.org/schema/context"
    	xsi:schemaLocation="
    		http://www.springframework.org/schema/beans 
    		http://www.springframework.org/schema/beans/spring-beans.xsd
    	    http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd">
            
    	<bean id="counter" class="constxiong.interview.threadsafe.Counter" />
    	
    </beans>

     

    测试类

    package constxiong.interview.threadsafe;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class CounterTest {
    	
    	public static void main(String[] args) {
    		final ApplicationContext context = new ClassPathXmlApplicationContext("spring_safe.xml");
    
    		for (int i = 0; i < 10; i++) {
    			new Thread(){
    				@Override
    				public void run() {
    					Counter counter = (Counter)context.getBean("counter");
    					for (int j = 0; j < 1000; j++) {
    						counter.addAndPrint();
    					}
    				}
    			}.start();
    		}
    		
    	}
    	
    }
    

    打印结果开头和结尾

    1
    5
    7
    4
    2
    6
    3
    8
    9
    .
    .
    .
    9818
    9819
    9820
    9821
    9822
    9823
    9824
    9825

    期望打印出的最大值应该是 10000

     

    修改 spring 配置文件,把 bean 的作用域改为 prototype

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xmlns:context="http://www.springframework.org/schema/context"
    	xsi:schemaLocation="
    		http://www.springframework.org/schema/beans 
    		http://www.springframework.org/schema/beans/spring-beans.xsd
    	    http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd">
            
    	<bean id="counter" class="constxiong.interview.threadsafe.Counter" scope="prototype"/>
    	
    </beans>

    测试结果输出10个 1000

    即每个线程都创建了一个 Counter 对象,线程内独自计数,不存在线程安全问题。但是不是我们想要的结果,打印出 10000。

     

    所以 spring 管理的 bean 的线程安全跟 bean 的创建作用域和 bean 所在的使用环境是否存在竞态条件有关,spring 并不能保证 bean 的线程安全。

     


    【Java面试题与答案】整理推荐

     

    展开全文
  • Spring Bean线程安全

    2017-05-07 11:06:59
    前两天在使用spring Bean的时候,发现跑出来的数据总是存在着一些奇怪的值,这些值在当前的处理当中本该不会出现,找了半天,发现时上一个线程使用该Bean后的遗留的值。后面查看了spring Bean的相关知识后,找到了...

        前两天在使用spring Bean的时候,发现跑出来的数据总是存在着一些奇怪的值,这些值在当前的处理当中本该不会出现,找了半天,发现时上一个线程使用该Bean后的遗留的值。后面查看了spring Bean的相关知识后,找到了问题的原因。 使用了ThreadLocal——线程本地变量的方式解决了问题。对问题产生的原因做一个分析和总结。

    一. 问题原因

        Spring框架里的Bean,默认为单例模式,这是在多线程开发的时候要尤其注意的地方。
        当多用户同时请求一个服务时,容器会给每一个请求分配一个线程,这是多个线程会并发执行该请求多对应的业务逻辑(成员方法),此时就要注意了,如果该处理逻辑中有对该单例Bean状态的修改(体现为该单例Bean的成员属性),则必须考虑线程同步问题。

    二. 使用ThreadLocal解决线程安全问题

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

    三. 线程安全的情况

    1. 常量始终是线程安全的,因为只存在读操作。
    2. 每次调用方法前都新建一个实例是线程安全的,因为不会访问共享的资源。
    3. 局部变量是线程安全的。因为每执行一个方法,都会在独立的空间创建局部变量,它不是共享的资源。局部变量包括方法的参数变量和方法内变量。

    四. 有状态与无状态

        有状态就是有数据存储功能。有状态对象(Stateful Bean),就是有实例变量的对象 ,可以保存数据,是非线程安全的。在不同方法调用间不保留任何状态。
        无状态就是一次操作,不能保存数据。无状态对象(Stateless Bean),就是没有实例变量的对象 .不能保存数据,是不变类,是线程安全的。
        无状态的Bean适合用不变模式,技术就是单例模式,这样可以共享实例,提高性能。
        有状态的Bean,多线程环境下不安全,那么适合用Prototype原型模式。Prototype: 每次对bean的请求都会创建一个新的Bean实例。

      欢迎关注个人公众号,本公众号用于日常技术分享
    这里写图片描述

    展开全文
  • Spring单例bean线程安全

    千次阅读 2018-03-29 17:04:43
    Spring容器中的bean默认是单例模式。当多个客户端同时请求一个服务时,容器会给每一个请求分配一个线程... Spring使用ThreadLocal解决线程安全问题。一般情况下,只有无状态的Bean才可以在多线程环境下共享。Sprin...
      Spring容器中的bean默认是单例模式。当多个客户端同时请求一个服务时,容器会给每一个请求分配一个线程。这些线程会并发执行该请求对应的业务处理逻辑(成员方法),如果该处理逻辑中有对该单例bean状态的修改(体现为该单例bean的成员属性),则需要考虑线程同步问题。
      S pring使用ThreadLocal解决线程安全问题。一般情况下,只有无状态的Bean才可以在多线程环境下共享。Spring对一些Bean(如RequestContextHolder、TransactionSynchronizationManager、LocaleContextHolder等)中“非线程安全状态”,采用ThreadLocal进行处理,让它们也成为线程安全的状态,因此有状态的Bean也可以在多线程中共享了。
      ThreadLocal和线程同步机制( synchronized)都可以解决多线程中“相同变量”的访问冲突问题。
      线程同步机制 synchronized) 通过“对象锁”, 保证同一时间只有一个线程访问变量, 让不同的线程排队访问。 这时该变量是多个线程共享的,使用同步机制要求程序慎密地分析什么时候对变量进行读写,什么时候需要锁定某个对象,什么时候释放对象锁等繁杂的问题,程序设计和编写难度相对较大。
      ThreadLocal会为每一个线程提供一个独立的“变量副本”,从而隔离了多个线程对数据的访问冲突。因为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。ThreadLocal提供了线程安全的共享对象,在编写多线程代码时,可以把不安全的变量封装进ThreadLocal。

      如果某一进程中有多个线程在同时运行,而这些线程又同时运行某段代码。假如每次运行结果和单线程运行的结果是一样的,而且其他变量的值也和预期的是一样的,就是线程安全的。如果一个类所提供的方法,对于线程来说是原子操作,或者多个线程之间的切换不会导致该接口的执行结果存在二义性,那么便不用考虑同步的问题。
      线程安全问题都是由全局变量及静态变量引起的。 若每个线程中对全局变量、静态变量只有读操作,而无写操作,这个全局变量是线程安全的。若有多个线程同时执行写操作,则需要考虑线程同步,否则就可能影响线程安全。
      ① 常量始终是线程安全的,因为只存在读操作。
      ② 每次调用方法前都新建一个实例是线程安全的,因为不会访问共享的资源。
      ③ 局部变量是线程安全的。因为每执行一个方法,都会在独立的空间创建局部变量,它不是共享的资源。局部变量包括方法的参数变量和方法内变量。
      有状态就是有数据存储功能。有状态对象(Stateful Bean),就是有实例变量的对象,可以保存数据,是非线程安全的。在不同方法调用间不保留任何状态。
      无状态就是一次操作,不能保存数据。无状态对象(Stateless Bean),就是没有实例变量的对象,不能保存数据,是不变类,是线程安全的。
    展开全文
  • Spring的单例Bean线程安全问题

    千次阅读 2019-10-22 15:57:32
    线程安全问题都是由成员变量及静态变量引起的。 若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的; 若有多个线程同时执行写操作,一般都需要考虑线程同步,否则就可能...
    • Spring框架里的bean,或者说组件,获取实例的时候都是默认的单例模式
    • 线程安全问题都是由成员变量及静态变量引起的。
    • 若每个线程中对成员变量、静态变量只有读操作,而无写操作,一般来说,这个成员变量、静态变量是线程安全的;
    • 若有多个线程同时执行写操作,一般都需要考虑线程同步,否则就可能影响线程安全。
    • 当多个线程调用方法时会不会出现线程安全问题呢?答案是不会,方法存在虚拟机栈中,是线程私有的。

    成员变量、局部变量、静态变量的区别

    成员变量局部变量静态变量
    别名实例变量类变量
    定义位置在类中,方法外方法中,或者方法的形式参数在类中,方法外
    初始化值有默认初始化值无,先定义,赋值后才能使用有默认初始化值
    调用方式对象调用对象调用,类名调用
    生命周期与对象共存亡与方法共存亡与类共存亡
    存储位置堆中栈中方法区

    推荐文章:
    聊一聊Spring中的线程安全性
    JVM内存模型

    展开全文
  • Spring框架中的单例Bean默认是单例模式,不是线程安全的。Spring框架并没有对单例Bean进行多线程的封装处理。 关于线程是否安全,可以从Bean的状态来考虑是否要进行处理,有状态的Bean就是有数据存储功能,例如VO...
  • Spring中的单例bean线程安全问题 因为成员变量是存放在堆内存中,而堆内存又是线程共享的,这就造成了线程安全问题 因为Spring中的Bean默认是单例的,所以在定义成员变量时也有可能会发生线程安全问题 单例的bean ...
  • Spring中的Bean线程安全的吗?

    万次阅读 多人点赞 2019-03-12 23:59:43
    Spring容器中的Bean是否线程安全,容器本身并没有提供Bean线程安全策略,因此可以说Spring容器中的Bean本身不具备线程安全的特性,但是具体还是要结合具体scope的Bean去研究。 Spring 的 bean 作用域(scope)类型...
  • Spring中的Bean是否线程安全和Spring无关。因为Spring只承担了创建和管理Bean的职责,并没有对Bean进行任何修改。 因为Ioc并不具备线程安全的特性,但是要看@Scope, 原型模式一定是线程安全的,因为每次都需要创建...
  • 出现线程安全问题的情况: 当Bean对象对应的存在可变的成员变量并且其中存在改变这个变量的线程时,多线程操作该Bean对象时会出现线程安全。 解决方案: Spring使用ThreadLocal解决单例模式Bean线程安全问题。...
  • Spring的bean默认scope属性为singleTon,即单例的,有线程安全问题 如果设置@Scope(“prototype”),则每次都会创建新对象,不存在线程安全问题 public static void main(String[] args) { ...
  • 容器本身并没有提供Bean线程安全策略,谈论Bean是否安全首先看一下它的作用范围: Spring 的 bean 作用域(scope)类型  1、singleton:单例,默认作用域。  2、prototype:原型,每次创建一个新对象。  3、...
  • 我们知道Spring相对于之前框架的明显一点区别就是Spring容器生成的Bean都是默认单例的,初读到这里的时候我也是有点疑惑,所以写这篇文章来谈谈线程安全和单例多例的问题。 在讲单例和线程安全之前首先我们要明白...
  • spring中bean线程安全问题

    千次阅读 2019-05-06 10:24:43
    Spring容器生成的Bean都是默认单例的,那么spring是怎么处理并发的情况下线程安全问题呢? 在讲单例和线程安全之前首先我们要明白一点,那就是在单例模式下多线程也可以同时访问同一个对象。单例模式顾名思义,所有...
  • 浅谈Spring中的BeanBean线程安全的吗?
  • Bean对象对应的中存在可变的成员变量,并且有改变这个变量的线程,多线程操作该Bean对象,总有一天会出现线程安全问题。   解决办法: 1. 在Bean对象()中尽量避免定义可变的成员变量;(个人觉得这个建议...
  • Spring中单例Bean线程安全的吗

    万次阅读 多人点赞 2019-09-02 17:16:15
    Spring容器中的Bean是否线程安全,容器本身并没有提供Bean线程安全策略,因此可以说Spring容器中的Bean本身不具备线程安全的特性,但是具体还是要结合具体scope的Bean去研究。 Spring 的 bean 作用域(scope)...
  • 事实上spring中bean线程安全性与spring是无关的,是和写的代码有关系! Spring的单例bean在多线程下是存在线程安全性问题的,主要是因为当多个线程同时操作同一个对象的时候,对这个对象的非静态成员变量的写操作...
  • Spring bean 和单例bean线程安全

    千次阅读 2018-10-12 18:17:17
    Bean的作用域  Spring 3中为Bean定义了5中作用域,分别为singleton(单例)、prototype(原型)、request、session和global session,5种作用域说明如下: singleton:单例模式,Spring IoC容器中只会存在一个...
  • 一、Spring单例模式与线程安全 Spring框架里的bean,或者说组件,获取实例的时候都是默认的单例模式,这是在多线程开发的时候要尤其注意的地方。 单例模式的意思就是只有一个实例。单例模式确保某一个只有...
  • Spring单例Bean线程安全

    万次阅读 2011-08-01 12:01:02
    Spring的bean默认都是单例的,这些单例Bean在多线程程序下如何保证线程安全呢?例如对于Web应用来说,Web容器对于每个用户请求都创建一个单独的Sevlet线程来处理请求,引入Spring框架之后,每个Action都是单例的,...
  • 在IOC容器启动之后,并不会马上就实例化相应的bean,此时容器仅仅拥有所有对象的BeanDefinition(BeanDefinition:是容器依赖某些工具加载的XML配置信息进行解析和分析,并将分析后的信息编组为相应的BeanDefinition)...
  • 一、在什么情况下,单例的Bean对象存在线程安全问题当Bean对象对应的存在可变的成员变量并且其中存在改变这个变量的线程时,多线程操作该Bean对象时会出现线程安全。二、原因当多线程中存在线程改变了bean对象的可...
  • spring bean线程安全

    千次阅读 2016-07-13 20:08:57
    在使用Spring框架时,很多时候不知道或者忽视了多线程的问题。因为写程序时,或做单元测试时,很难有机会碰到多线程的问题,因为没有那么容易模拟多线程测试的环境。但如果不去考虑潜在的漏洞,它就会变成程序的隐形...
  • Spring容器中的Bean是否线程安全,容器本身并没有提供Bean线程安全策略,因此可以说Spring容器中的Bean本身不具备线程安全的特性,但是具体还是要结合具体scope的Bean去研究。 Spring 的 bean 作用域(scope)...
  • 说这个问题,首先需要知道在什么环境下会...这样的话,spring 的 bean 是否存在线程安全问题,主要就要看是否具有状态性了。 spring的bean基本不会对数据进行操作,从这个层面来说,它是无状态的,也就是没有通过数据的
  • 如何保证spring bean中的线程安全

    千次阅读 2016-01-30 10:23:01
    写在前面:这两天做了一个查询接口,由于查询条件和参数太多,采用了链式操作,链式操作的是个...最终通过检索关键字“spring bean 线程安全”找到了答案: [url]http://www.cnblogs.com/doit8791/p/4093808.ht...
  • Spring容器本身没有提供Bean线程安全策略,因此,也可以说Spring容器中的bean不是线程安全的。 ​ 如何处理线程安全问题,分情况讨论: ​ Spring的作用域(scope): singleton:单例,默认作用域。 prototype:...
  • 单例 bean 存在线程问题,主要是因为当多个线程操作同一个对象的时候,对这个对象的非静态成员变量的写操作会存在线程安全问题。 常见的有两种解决办法: 在Bean对象中尽量避免定义可变的成员变量(不太现实)。...
  • 作者:myseriescnblogs.com/myseries/p/11729800.html结论:不是线程安全的Spring容器中的Bean是否线程安全,容器本身并没有提供Bean的线...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 68,532
精华内容 27,412
关键字:

线程安全bean类