首页 > 其他分享 >单例 Bean 的线程安全问题

单例 Bean 的线程安全问题

时间:2022-10-22 19:23:32浏览次数:49  
标签:变量 ThreadLocal Bean 线程 单例 多线程

最近面试遇到一个问题:单例 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。对多线程性能有一定影响(此方法没试验过 慎用!);

标签:变量,ThreadLocal,Bean,线程,单例,多线程
From: https://www.cnblogs.com/JayZzzWh/p/16817089.html

相关文章

  • go语言设计模式-单例模式
    GetInstance方法开放了instance变量的读权限,使得只能读到instance,而不能对其赋值varinstance*singelton=new(singelton),饿汉式:在main执行之前,编译期间通过new就已经被......
  • 使用同步代码块解决线程安全问题
    使用同步代码块解决线程安全问题packageA_ShangGuiGu.Thread.ThreadDemo;​/***例子:三个窗口买票,使用实现Runnable接口的方法。*1.出现的问题:卖票过程中出现了重票,错......
  • 进程与线程的区别
     线程与进程的根本区别是进程是操作系统资源分配的基本单位,而线程是处理器任务调度和执行的基本单位。  在引入了线程的操作系统中,通常一个进程都有若干个线程,至少包......
  • devexpress中grid控件教程 多线程异步加载数据,进度条展示
    devexpress中最强大的控件,要数它的Grid了。几乎任务数据都可以展示,但今天要用它做另一个功能。假设我们开发这样一款软件:视频编辑软件。里面有个功能,提取视频中的音频。一......
  • 进程与线程
    简介1、进程进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,简而言之就是程序的一次执行过程,也可以直接理解为电脑上的软件的运行情况,通过电脑的任务管......
  • 多线程
    线程简介多任务现实中太多同时做多件事情的例子,看起来是多个任务都在做,其实本质上我们的大脑同时只做了一件事多线程原来是一条路,慢慢因为车太多了,道路阻塞,效率极......
  • UEC++ 多线程(二) AsyncTask
    AsyncTaskAsyncTask系统实现的多线程与自己实现继承的FRunnable实现的原理相似,还可以利用UE4提供的线程池。当使用多线程不满意时也可以调用StartSynchronousTask改成主线......
  • 线程与进程
    今天我们就来主要介绍一下什么是线程和进程,线程和进程并没有表面上看起来这么简单。一、进程定义:进程是一个具有一定独立功能的程序在一个数据集上的一次动态执行的过程,......
  • 单核多线程可见性问题
    背景学习群上有个同学提出问题,如下截图这里可以看到分歧点,我认为JMM协议规定了工作内存,那么即使是单核,JAVA虚拟机也会保证线程本地内存变量的私有性,所以会存在不可见。......
  • java线程的优先级
    packageA_ShangGuiGu.Thread.ThreadDemo;/***优先级*1.MAX_Priority-----最大优先级为10*2.MIN_Priority-----最小优先级为1*3.NORM_Priority----默认优先级5*4......