最近面试遇到一个问题:单例 Bean 的线程安全问题怎么解决的。

之前了解但是没有深究它的解决方法。大部分时候我们并没有在项目中使用多线程,所以很少有人会关注这个问题。

大部分 Bean 实际都是无状态(没有实例变量)的(比如 Dao、Service),这种情况下, Bean 是线程安全的。

因为Spring 默认情况下是单例的(singleton)。所有我们会遇见多个线程操作同一个对象的时候是存在资源竞争的问题。

常见的有两种解决办法:

  1. 在 Bean 中尽量避免定义可变的成员变量。

  2. 在类中定义一个 ThreadLocal 成员变量,将需要的可变成员变量保存在 ThreadLocal 中(推荐的一种方式)。

    ​ 在同步机制中,通过对象的锁机制保证同一时间只有一个线程访问变量。这时该变量是多个线程共享的,使用同步机制要求程序慎密地分析什么时候对变量进行读写,什么时候需要锁定某个对象,什么时候释放对象锁等繁杂的问题,程序设计和编写难度相对较大。

      而ThreadLocal则从另一个角度来解决多线程的并发访问。ThreadLocal会为每一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。因为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。不同线程只操作自己线程的副本变量。

    ThreadLocal提供了线程安全的共享对象,在编写多线程代码时,可以把不安全的变量封装进ThreadLocal

    ThreadLocal代码举例

     private  static ThreadLocal<Integer> content=new ThreadLocal<Integer>(){
    
             protected  Integer initalValue(){
                    return (int)(Math.random()*10+100);
                }
    
        };
    
        private  static ThreadLocal<Integer> test=new ThreadLocal<Integer>(){
    
            protected String initalValue(){
                return "单例模式是不安全的" +(int)(Math.random()*10+100);
            }
        };
    public Object get(){
            System.out.println(content.get());
            System.out.println(test.get());
            System.out.println();
            return  test.get();
        }
    
  3. 将有状态的bean的作用域由“singleton”改为“prototype”。( 如注解 : @Scope(“prototype”) );

  4. 使用线程同步,加关键字synchronized。对多线程性能有一定影响(此方法没试验过 慎用!);

原文地址:http://www.cnblogs.com/JayZzzWh/p/16817089.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性