Spring为什么是单例的?如何保证线程安全?

单例的好处:

1 减少请求时候创建对象的开销,提升性能

2 减少jvm垃圾回收

单例的坏处:

1 对于有状态的变量可能会造成线程安全问题,因为只有一个实例,如果操作的是有状态的全局变量,多个线程之间可能会操作同一个变量和对象导致线程不安全问题

 

多例的好处:

1 线程安全,每个请求过来都分配一个新的对象,里面的所有东西属性方法都是该线程独享的

坏处:

1 资源开销大,创建对象需要消耗性能

2 会产生大量的垃圾对象

 

Spring框架中的bean 或者说组件,默认是单例的。
单例模式确保了某个类只有一个实例,并且自行实例化,向整个系统提供这个实例。
在多线程的情况下,Web容器会向每个请求分配一个线程。这些线程会执行对应的业务逻辑。如果在执行的时候对单例对象进行了修改,则必须考虑到线程同步的问题。

同步机制
ThreadLocal 和 线程同步机制
  线程同步机制中,通过对象的锁机制保证同一时间只有一个线程访问变量。这时该变量是多个线程共享的,使用同步机制要求程序慎密地分析什么时候对变量进行读写,什么时候需要锁定某个对象,什么时候释放对象锁等繁杂的问题。
  ThreadLocal会为每一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。因为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。ThreadLocal提供了线程安全的共享对象,在编写多线程代码时,可以把不安全的变量封装进ThreadLocal。

对于多线程资源共享的问题,同步机制采用了“以时间换空间”的方式,而ThreadLocal采用了“以空间换时间”的方式。前者仅提供一份变量,让不同的线程排队访问,而后者为每一个线程都提供了一份变量,因此可以同时访问而互不影响。 


在spring 中是使用 ThreadLocal 解决线程安全问题
线程安全问题主要是全局变量和静态变量引起的。
若每个线程中对全局变量、静态变量读操作,而无写操作,一般来说这个全局变量是线程安全的。
若多个线程同时执行写操作,需要考虑线程同步问题,否则影响线程安全。
spring 使用ThreadLocal 实现高并发下 共享资源的同步。

原理:
  为每一个使用该变量的线程都提供一个变量值的副本,是每一个线程都可以独立地改变自己的副本,而不会和其它线程的副本冲突。从线程的角度看,就好像每一个线 
程都完全拥有该变量。【每个线程其实是改变的是自己线程的副本,而不是真正要改变的变量,所以效果就是每个线程都有自己的,“这其实就将共享变相为人人有份!”】 

ThreadLocal 如何实现为每一个变量维护变量的副本。

public void set(T value) {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null)
        map.set(this, value);
    else
        createMap(t, value);
}

  • 3
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值